ทำไมคุณถึงต้องการประเภทที่สูงกว่า


13

บางภาษาอนุญาตให้มีการเรียนและฟังก์ชั่นที่มีพารามิเตอร์ชนิด (เช่นList<T>ที่Tอาจจะเป็นประเภทพล) ตัวอย่างเช่นคุณสามารถมีฟังก์ชั่นเช่น:

List<S> Function<S, T>(List<T> list)

อย่างไรก็ตามบางภาษาอนุญาตให้แนวคิดนี้ขยายได้สูงกว่าหนึ่งระดับช่วยให้คุณมีฟังก์ชั่นที่มีลายเซ็น:

K<S> Function<K<_>, S, T>(K<T> arg)

โดยที่K<_>ตัวเองเป็นประเภทเช่นList<_>นั้นมีพารามิเตอร์ประเภท "บางส่วนประเภท" นี้เรียกว่าตัวสร้างประเภท

คำถามของฉันคือทำไมคุณถึงต้องการความสามารถนี้ มันสมเหตุสมผลที่จะมีรูปแบบเหมือนกันList<T>เพราะทุกอย่างList<T>เกือบจะเหมือนกัน แต่สิ่งที่K<_>แตกต่างกันอย่างสิ้นเชิง คุณสามารถมีOption<_>และ a List<_>ที่ไม่มีฟังก์ชั่นทั่วไปเลย


7
มีคำตอบที่ดีหลายอย่างที่นี่: stackoverflow.com/questions/21170493/…
itsbruce

3
@itsbruce โดยเฉพาะFunctorตัวอย่างในคำตอบของ Luis Casillas นั้นค่อนข้างใช้งานง่าย ทำอะไรList<T>และOption<T>มีเหมือนกัน? ถ้าคุณให้ฉันคนใดคนหนึ่งและฟังก์ชั่นT -> Sที่ฉันสามารถให้คุณหรือList<S> Option<S>สิ่งที่พวกเขามีเหมือนกันคือคุณสามารถลองรับประโยชน์Tจากทั้งสองอย่าง
Doval

@Doval: คุณจะทำอดีตอย่างไร IReadableHolder<T>เท่าที่หนึ่งมีความสนใจในหลังผมจะคิดว่าอาจจะมีการจัดการโดยมีทั้งชนิดใช้
supercat

@supercat ฉันคาดเดาพวกเขาจะต้องดำเนินการIMappable<K<_>, T>ด้วยวิธีK<S> Map(Func<T, S> f)การดำเนินการเป็น,IMappable<Option<_>, T> IMappable<List<_>, T>ดังนั้นคุณจะต้อง จำกัดK<T> : IMappable<K<_>, T>การใช้ประโยชน์จากมัน
GregRos

1
การคัดเลือกไม่ใช่การเปรียบเทียบที่เหมาะสม สิ่งที่ทำกับคลาสประเภท (หรือโครงสร้างที่คล้ายกัน) คือคุณแสดงให้เห็นว่าประเภทที่กำหนดให้เป็นไปตามประเภทชนิดที่สูงขึ้น ซึ่งมักจะเกี่ยวข้องกับการกำหนดฟังก์ชั่นใหม่หรือแสดงฟังก์ชั่นที่มีอยู่ (หรือวิธีการถ้ามันเป็นภาษา OO เช่น Scala) สามารถใช้ เมื่อทำสิ่งนี้เสร็จแล้วฟังก์ชั่นใด ๆ ที่กำหนดให้ทำงานกับประเภทที่สูงกว่าจะใช้ได้กับประเภทนั้นทั้งหมด แต่มันเป็นอะไรที่มากกว่าอินเตอร์เฟสเพราะมีการกำหนดชุดฟังก์ชัน / เมธอดอย่างง่ายมากกว่า ฉันเดาว่าฉันจะต้องไปและเขียนคำตอบเพื่อแสดงว่ามันทำงานอย่างไร
58

คำตอบ:


5

เนื่องจากไม่มีใครตอบคำถามฉันคิดว่าฉันจะไปด้วยตัวเอง ฉันจะต้องได้รับปรัชญาเล็กน้อย

การเขียนโปรแกรมทั่วไปเกี่ยวกับการทำให้เป็นนามธรรมมากกว่าประเภทที่คล้ายกันโดยไม่สูญเสียข้อมูลประเภท (ซึ่งเป็นสิ่งที่เกิดขึ้นกับความแตกต่างของค่าเชิงวัตถุ) ในการดำเนินการนี้ประเภทต่างๆจะต้องใช้อินเทอร์เฟซบางอย่างร่วมกัน (ชุดของการดำเนินการไม่ใช่คำศัพท์ OO) ที่คุณสามารถใช้ได้

ในภาษาเชิงวัตถุชนิดตอบสนองอินเทอร์เฟซโดยอาศัยชั้นเรียน แต่ละคลาสมีอินเตอร์เฟสของตัวเองซึ่งถูกกำหนดเป็นส่วนหนึ่งของชนิด เนื่องจากคลาสทั้งหมดList<T>นั้นใช้อินเทอร์เฟซร่วมกันคุณจึงสามารถเขียนโค้ดที่ทำงานได้ไม่ว่าTคุณจะเลือกแบบใด อีกวิธีหนึ่งในการกำหนดอินเทอร์เฟซคือข้อ จำกัด ในการสืบทอดและแม้ว่าทั้งสองจะดูแตกต่างกัน แต่ก็คล้ายกันถ้าคุณคิด

ในภาษาเชิงวัตถุส่วนใหญ่List<>ไม่ได้เป็นประเภทที่เหมาะสมในตัวเอง มันไม่มีวิธีการดังนั้นจึงไม่มีส่วนต่อประสาน มันเป็นสิ่งเดียวList<T>ที่มีสิ่งเหล่านี้ *โดยเฉพาะอย่างยิ่งในแง่ทางเทคนิคเพิ่มเติมประเภทเดียวที่คุณสามารถมีความหมายเป็นนามธรรมมากกว่าเป็นผู้ที่มีชนิด เพื่อที่จะใช้ประโยชน์จากชนิดที่สูงกว่าในโลกเชิงวัตถุคุณต้อง จำกัด ประเภทวลีในลักษณะที่สอดคล้องกับข้อ จำกัด นี้

ยกตัวอย่างเช่นเป็นที่กล่าวถึงในความคิดเห็นที่เราสามารถดูOption<>และList<>เป็น "mappable" ในแง่ที่ว่าถ้าคุณมีฟังก์ชั่นที่คุณสามารถแปลงOption<T>เป็นOption<S>หรือเป็นList<T> List<S>โปรดจำไว้ว่าคลาสไม่สามารถนำมาใช้เพื่อนามธรรมผ่านประเภทที่สูงกว่าได้โดยตรงเราจึงสร้างอินเทอร์เฟซแทน:

IMappable<K<_>, T> where K<T> : IMappable<K<_>, T>

และจากนั้นเราใช้อินเตอร์เฟซทั้งในList<T>และOption<T>เป็นIMappable<List<_>, T>และIMappable<Option<_>, T>ตามลำดับ สิ่งที่เราได้ทำคือการใช้ประเภทสูง kinded ข้อ จำกัด ขึ้นในวันที่เกิดขึ้นจริง (ไม่ใช่สูง kinded) ประเภทและOption<T> List<T>นี่เป็นวิธีที่ทำใน Scala แต่แน่นอนว่า Scala มีคุณสมบัติเช่นลักษณะตัวแปรประเภทและพารามิเตอร์โดยนัยที่ทำให้แสดงออกได้มากขึ้น

ในภาษาอื่น ๆ มันเป็นไปได้ที่จะแยกแยะประเภทที่สูงกว่าโดยตรง ใน Haskell หนึ่งในหน่วยงานที่มีอำนาจสูงสุดในระบบการพิมพ์เราสามารถสร้างคลาสประเภทสำหรับประเภทใด ๆ แม้ว่าจะมีประเภทที่สูงกว่าก็ตาม ตัวอย่างเช่น,

class Mappable mp where
    map :: mp a -> mp b

นี่คือข้อ จำกัด วางโดยตรงบนชนิด (ไม่ได้ระบุ) mpซึ่งจะนำพารามิเตอร์ชนิดหนึ่งและต้องมันจะเกี่ยวข้องกับฟังก์ชั่นmapที่จะเปลี่ยนเป็นmp<a> mp<b>จากนั้นเราสามารถเขียนฟังก์ชั่นที่ จำกัด ประเภทที่สูงกว่าโดยMappableเหมือนกับภาษาเชิงวัตถุที่คุณสามารถวางข้อ จำกัด การสืบทอด เรียงกันของ

เมื่อต้องการสรุปสิ่งต่างๆความสามารถในการใช้ประเภทที่สูงกว่านั้นขึ้นอยู่กับความสามารถของคุณในการ จำกัด หรือใช้เป็นส่วนหนึ่งของข้อ จำกัด ประเภท


เคยยุ่งกับการเปลี่ยนงาน แต่ในที่สุดจะหาเวลาเขียนคำตอบของตัวเอง ฉันคิดว่าคุณถูกรบกวนด้วยความคิดเรื่องข้อ จำกัด สิ่งสำคัญอย่างหนึ่งของประเภทที่สูงกว่าคือพวกมันอนุญาตให้กำหนดฟังก์ชัน / พฤติกรรมซึ่งสามารถนำไปใช้กับประเภทใดก็ได้ที่สามารถแสดงเหตุผลได้ ไกลจากข้อ จำกัด ที่กำหนดในประเภทที่มีอยู่แล้วประเภทของคลาส (แอปพลิเคชันประเภทที่สูงกว่าประเภทหนึ่ง) เพิ่มพฤติกรรมให้พวกเขา
itsbruce

ฉันคิดว่ามันเป็นปัญหาของความหมาย คลาสชนิดกำหนดคลาสประเภท เมื่อคุณกำหนดฟังก์ชั่นเช่น(Mappable mp) => mp a -> mp bคุณได้วางข้อ จำกัด ในการที่จะเป็นสมาชิกของชั้นชนิดmp Mappableเมื่อคุณประกาศประเภทเช่นเป็นOptionตัวอย่างของMappableคุณเพิ่มพฤติกรรมให้กับประเภทนั้น ฉันเดาว่าคุณสามารถใช้ประโยชน์จากพฤติกรรมนั้นได้โดยไม่ จำกัด ประเภทใด ๆ แต่ก็ไม่แตกต่างจากการกำหนดฟังก์ชันทั่วไป
GregRos

นอกจากนี้ฉันค่อนข้างเรียนบางประเภทไม่เกี่ยวข้องโดยตรงกับประเภทที่สูงขึ้น Scala มีประเภทที่สูงกว่า แต่ไม่ได้พิมพ์คลาสและคุณสามารถ จำกัด คลาสของประเภทเป็นประเภทที่มีประเภท*โดยไม่ทำให้พวกเขาใช้ไม่ได้ เป็นเรื่องจริงที่คลาสประเภทนั้นจะทรงพลังมากเมื่อทำงานกับประเภทที่มีระดับสูงกว่า
GregRos

Scala มีคลาสประเภท มีการใช้งานโดยนัย implicits จัดให้เทียบเท่ากับอินสแตนซ์คลาสประเภท Haskell เป็นการใช้งานที่บอบบางกว่า Haskell เนื่องจากไม่มีไวยากรณ์เฉพาะสำหรับมัน แต่มันก็เป็นหนึ่งในจุดประสงค์สำคัญของ Scala โดยนัยและพวกเขาทำงาน
itsbruce
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.