ตู้คอนเทนเนอร์ขนาดคงที่ทั้งหมดนั้นเป็นฟังก์ชั่นโมโนเรดที่แข็งแกร่งหรือไม่


9

Applicativetypeclass หมายถึงหละหลวม monoidal functors ที่รักษาโครงสร้าง monoidal คาร์ทีเซียนในหมวดหมู่ของฟังก์ชั่นพิมพ์

กล่าวอีกนัยหนึ่งได้รับ isomorphisms บัญญัติซึ่ง(,)เป็นรูปแบบโครงสร้าง monoidal:

-- Implementations left to the motivated reader
assoc_fwd :: ((a, b), c) -> (a, (b, c))
assoc_bwd :: (a, (b, c)) -> ((a, b), c)

lunit_fwd :: ((), a) -> a
lunit_bwd :: a -> ((), a)

runit_fwd :: (a, ()) -> a
runit_bwd :: a -> (a, ())

typeclass และกฎหมายของมันสามารถเขียนแบบนี้ได้:

class Functor f => Applicative f
  where
  zip :: (f a, f b) -> f (a, b)
  husk :: () -> f ()

-- Laws:

-- assoc_fwd >>> bimap id zip >>> zip
-- =
-- bimap zip id >>> zip >>> fmap assoc_fwd

-- lunit_fwd
-- =
-- bimap husk id >>> zip >>> fmap lunit_fwd

-- runit_fwd
-- =
-- bimap id husk >>> zip >>> fmap runit_fwd

บางคนอาจสงสัยว่าสิ่งที่นักแสดงที่oplax monoidal เกี่ยวกับโครงสร้างเดียวกันอาจมีลักษณะ:

class Functor f => OpApplicative f
  where
  unzip :: f (a, b) -> (f a, f b)
  unhusk :: f () -> ()

-- Laws:

-- assoc_bwd <<< bimap id unzip <<< unzip
-- =
-- bimap unzip id <<< unzip <<< fmap assoc_bwd

-- lunit_bwd
-- =
-- bimap unhusk id <<< unzip <<< fmap lunit_bwd

-- runit_bwd
-- =
-- bimap id unhusk <<< unzip <<< fmap runit_bwd

หากเรานึกถึงประเภทที่เกี่ยวข้องกับคำจำกัดความและกฎหมายความจริงที่น่าผิดหวังจะถูกเปิดเผย OpApplicativeไม่มีข้อ จำกัด เจาะจงกว่าFunctor:

instance Functor f => OpApplicative f
  where
  unzip fab = (fst <$> fab, snd <$> fab)
  unhusk = const ()

อย่างไรก็ตามในขณะที่Applicativefunctor ทุกคน(จริง ๆFunctor) OpApplicativeมีความสำคัญไม่จำเป็นต้องมีความสัมพันธ์ที่ดีระหว่างApplicativelaxities และOpApplicativeoplaxities ดังนั้นเราสามารถมองหาฟังก์ชั่นที่แข็งแกร่ง monoidal wrt โครงสร้าง monoidal คาร์ทีเซียน:

class (Applicative f, OpApplicative f) => StrongApplicative f

-- Laws:
-- unhusk . husk = id
-- husk . unhusk = id
-- zip . unzip = id
-- unzip . zip = id

กฎหมายข้างต้นเป็นครั้งแรกเล็กน้อยเนื่องจากเพียงอาศัยของชนิดเป็นฟังก์ชั่นในตัวตน() -> ()()

อย่างไรก็ตามกฎสามข้อที่เหลืออยู่และด้วยเหตุนี้คลาสย่อยเองจึงไม่ใช่เรื่องเล็กน้อย โดยเฉพาะไม่ทุกคนApplicativeเป็นตัวอย่างที่ถูกต้องตามกฎหมายของชั้นนี้

นี่คือฟังก์ชั่นบางอย่างApplicativeที่เราสามารถประกาศอินสแตนซ์ที่ถูกกฎหมายของStrongApplicative:

  • Identity
  • VoidF
  • (->) r
  • Monoid m => (,) m (ดูคำตอบ)
  • Vec (n :: Nat)
  • Stream (อนันต์)

และนี่คือบางส่วนApplicativeที่เราไม่สามารถ:

  • []
  • Either e
  • Maybe
  • NonEmptyList

รูปแบบที่นี่แสดงให้เห็นว่าStrongApplicativeระดับอยู่ในความรู้สึกที่FixedSizeระดับที่ "ขนาดคงที่" *หมายความว่าหลายหลาก**ของชาวaในที่อยู่อาศัยของf aการแก้ไข

สิ่งนี้สามารถกล่าวได้ว่าเป็นสองการคาดเดา:

  • ทุกคนที่Applicativeเป็นตัวแทนของภาชนะ "ขนาดคงที่" ขององค์ประกอบของการโต้แย้งประเภทของมันเป็นตัวอย่างของStrongApplicative
  • ไม่มีอินสแตนซ์ที่StrongApplicativeมีจำนวนครั้งของการเกิดขึ้นซึ่งaแตกต่างกันไป

ทุกคนสามารถนึกถึงตัวอย่างที่หักล้างการคาดเดาเหล่านี้หรือเหตุผลที่น่าเชื่อถือบางอย่างที่แสดงให้เห็นว่าทำไมพวกเขาถึงเป็นจริงหรือเท็จ?


* ฉันรู้ว่าฉันยังไม่ได้กำหนดคำคุณศัพท์ "ขนาดคงที่" อย่างถูกต้อง น่าเสียดายที่งานมีลักษณะกลมเล็กน้อย ฉันไม่รู้คำอธิบายที่เป็นทางการของคอนเทนเนอร์ "ขนาดคงที่" และฉันพยายามหาที่มา StrongApplicativeเป็นความพยายามที่ดีที่สุดของฉันจนถึงตอนนี้

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

ไม่ได้ตระหนักถึงคำจำกัดความที่เป็นทางการที่มีอยู่ฉันกำลังขอร้องให้สัญชาตญาณในการใช้คำว่า "ขนาดคงที่" อย่างไรก็ตามถ้ามีคนรู้อยู่แล้วเกี่ยวกับพิธีการที่มีอยู่สำหรับขนาดของนักแสดงและสามารถเปรียบเทียบStrongApplicativeกับมันได้ดีกว่ามาก

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

การที่ไม่แม่นยำเกี่ยวกับเรื่องนี้ทำให้เกิดความสับสนในความเห็นดังนั้นนี่คือตัวอย่างของสิ่งที่ฉันจะพิจารณาขนาด / หลายหลากของฟังก์ชั่นต่างๆเป็น:

  • VoidF: แก้ไขแล้ว 0
  • Identity: แก้ไขแล้ว 1
  • Maybe: ตัวแปรขั้นต่ำ 0 สูงสุด 1
  • []: ตัวแปร 0 ต่ำสุดสูงสุดไม่ จำกัด
  • NonEmptyList: ตัวแปรขั้นต่ำ 1 สูงสุดไม่ จำกัด
  • Stream: แก้ไขไม่มีที่สิ้นสุด
  • Monoid m => (,) m: แก้ไขแล้ว 1
  • data Pair a = Pair a a: แก้ไขแล้ว 2
  • Either x: ตัวแปรขั้นต่ำ 0 สูงสุด 1
  • data Strange a = L a | R a: แก้ไขแล้ว 1

ความคิดเห็นไม่ได้มีไว้สำหรับการอภิปรายเพิ่มเติม การสนทนานี้ได้รับการย้ายไปแชท
Samuel Liew

หนึ่งคำจำกัดความที่เป็นไปได้ของ "ขนาดคงที่" จะเป็น "ตัวแทน" ฟังก์ชั่นที่ใช้งานได้ทั้งหมดเป็นแอพพลิเคชั่นที่แข็งแกร่งตามความหมายที่อธิบายไว้ที่นี่เพราะ(->) rมันคือ isomorphic ในแบบที่ถูกต้อง
Daniel Wagner

@DanielWagner ฉันคิดว่าคุณต้องการมากกว่าเพียงแค่มอร์ฟเพื่อสืบทอด applicative ที่แข็งแกร่งจาก(->) r; คุณต้องการส่วนประกอบของ isomorphism เพื่อรักษาโครงสร้างการใช้งานที่แข็งแกร่ง ด้วยเหตุผลบางอย่างRepresentable typeclass ใน Haskell มีtabulate . return = returnกฎหมายลึกลับ(ซึ่งไม่ได้ใช้กับผู้ที่ไม่ใช่ monadic functors) แต่มันทำให้เรามี 1/4 ของเงื่อนไขที่เราจำเป็นต้องพูดtabulateและzipเป็น morphisms ของ monoids ประเภทที่เหมาะสม . อีก 3 ข้อเป็นกฎหมายเพิ่มเติมที่คุณต้องเรียกร้อง
ซาด Saeeduddin

ขออภัยนั่นควรเป็น " tabulateและindexเป็น morphisms ของหมวดหมู่ที่เหมาะสม ... "
Asad Saeeduddin

@ AsadSaeeduddin วิธีการที่กฎหมายระบุไว้ในเอกสารนั้นมีความเฉพาะเจาะจงอย่างผิดปกติบางที แต่มันกลับกลายเป็นว่าการต้องการreturnไม่ใช่ปัญหาร้ายแรง cotraverse getConst . Constเป็นการใช้งานเริ่มต้นสำหรับreturn/ pureในแง่ของDistributiveและเนื่องจากตัวแทนจำหน่าย / Representables มีรูปร่างคงที่การใช้งานนั้นไม่ซ้ำกัน
duplode

คำตอบ:


4
  • ทุกคนที่Applicativeเป็นตัวแทนของภาชนะ "ขนาดคงที่" ขององค์ประกอบของการโต้แย้งประเภทของมันเป็นตัวอย่างของStrongApplicative
  • ไม่มีอินสแตนซ์ที่StrongApplicativeมีจำนวนครั้งของการเกิดขึ้นซึ่งaแตกต่างกันไป

ทุกคนสามารถนึกถึงตัวอย่างที่หักล้างการคาดเดาเหล่านี้หรือเหตุผลที่น่าเชื่อถือบางอย่างที่แสดงให้เห็นว่าทำไมพวกเขาถึงเป็นจริงหรือเท็จ?

ฉันไม่แน่ใจเกี่ยวกับการคาดเดาครั้งแรกและจากการพูดคุยกับ @AsadSaeeduddin เป็นไปได้ยากที่จะพิสูจน์ แต่การคาดเดาครั้งที่สองเป็นเรื่องจริง เพื่อดูว่าทำไมพิจารณาStrongApplicativeกฎหมายhusk . unhusk == id; นั่นคือทั้งหมด,x :: f () husk (unhusk x) == xแต่ในแฮสเค็ลล์unhusk == const ()กฎหมายก็เทียบเท่ากับการพูดเพื่อทุกคนx :: f (), husk () == x. แต่ในทางกลับกันก็หมายความว่ามีเพียงค่าที่แตกต่างกันประเภทหนึ่งเท่านั้นf (): หากมีสองค่าx, y :: f ()แล้วx == husk ()และเพื่อให้husk () == y x == yแต่ถ้ามีเพียงf ()ค่าเดียวที่เป็นไปได้fจะต้องมีรูปร่างคงที่ (เช่นสำหรับdata Pair a = Pair a aมีค่าประเภทเดียวเท่านั้นPair ()สิ่งมีชีวิตนี้Pair () ()แต่มีหลายประเภทค่าMaybe ()หรือ[()].) ดังนั้นhusk . unhusk == idบอกเป็นนัยว่าfจะต้องมีรูปร่างคงที่


ฮึ่ม เป็นที่ชัดเจนหรือไม่ว่า "มีค่าที่แตกต่างกันประเภทเดียวเท่านั้นf ()" หมายถึง "จำนวนการเกิดขึ้นของaไม่สามารถเปลี่ยนแปลง" ในการปรากฏตัวของ GADT และสิ่งแฟนซี?
Daniel Wagner

@DanielWagner ปรากฎว่า“ จำนวนครั้งที่aไม่สามารถเปลี่ยนแปลงได้” นั้นไม่เพียงพอสำหรับStrongApplicativeอินสแตนซ์ ตัวอย่างเช่นdata Writer w a = Writer (w,a)มีหลายหลากที่ไม่แตกต่างกันแต่ไม่ได้เป็นa StrongApplicativeคุณต้องการรูปร่างของนักแสดงที่จะไม่เปลี่ยนแปลงซึ่งฉันเชื่อว่าเป็นผลมาจากf ()การเป็นโสด
bradrn

ฉันไม่แน่ใจว่าฉันเห็นว่ามันเกี่ยวข้องอย่างไร ในคำตอบในขณะที่ยืนยันการคาดเดาครั้งที่สองคุณยืนยันว่า "การสมัครที่ดี" หมายถึง "หนึ่งที่ชัดเจนf ()" หมายถึง "จำนวนเหตุการณ์ที่aไม่สามารถเปลี่ยนแปลง" ฉันคัดค้านว่าขั้นตอนสุดท้ายของการโต้แย้งนั้นไม่เป็นความจริงอย่างชัดเจน data Weird a where One :: a -> Weird a; None :: Weird Boolเช่นพิจารณา มีค่าของประเภทที่Weird ()แตกต่างกัน แต่ตัวสร้างที่แตกต่างกันมีจำนวนaภายในที่แตกต่างกัน (มันไม่ใช่ตัวอย่างเต็มรูปแบบที่นี่เพราะFunctorยาก แต่เราจะรู้ได้อย่างไรว่าไม่สามารถแก้ไขได้)
Daniel Wagner

@DanielWagner จุดที่ดีที่Weird ()เป็นซิงเกิลตัน แต่มันไม่ใช่รูปร่างคงที่ แต่Weirdไม่ใช่เป็นFunctorดังนั้นจึงไม่สามารถเป็นStrongApplicativeได้ ฉันคิดว่าการคาดคะเนที่เกี่ยวข้องจะ: ถ้าfเป็น a Functor, f ()การเป็นซิงเกิลตันเป็นการบ่งบอกว่าfเป็นรูปร่างคงที่หรือไม่? ฉันสงสัยอย่างยิ่งว่าสิ่งนี้จะเป็นจริง แต่อย่างที่คุณสังเกตเห็นว่าฉันยังไม่มีข้อพิสูจน์
bradrn

5

เราสามารถตอบคำถามเหล่านี้อย่างน้อยหนึ่งคำถามในเชิงลบ:

ทุกการใช้งานที่เป็นตัวแทนของคอนเทนเนอร์ "ขนาดคงที่" ขององค์ประกอบของอาร์กิวเมนต์ชนิดเป็นตัวอย่างของ StrongApplicative

อันที่จริงตัวอย่างหนึ่งของกฎหมายStrongApplicativeในคำถามเดิมนั้นผิด ผู้สมัครMonoid => (,) mไม่ได้StrongApplicativeเป็นเช่นนั้นhusk $ unhusk $ ("foo", ()) == ("", ()) /= ("foo", ())นั้น

ตัวอย่างของคอนเทนเนอร์ขนาดคงที่:

data Strange a = L a | R a

ของ multiplicity คงที่ 1 ไม่ใช่การใช้ที่แข็งแกร่งเพราะถ้าเรานิยามhusk = Leftแล้วhusk $ unhusk $ Right () /= Right ()และในทางกลับกัน วิธีที่เท่าเทียมกันในการดูนี่คือนี่เป็นเพียงแอพพลิเคชั่นสำหรับนักเขียนที่คุณเลือกBoolสำหรับทางเลือกของหนังสือบน

ดังนั้นจึงมีผู้สมัคร "ขนาดคงที่" ที่ไม่ได้StrongApplicativeเป็น ไม่ว่าStrongApplicativeจะเป็นขนาดคงที่ทั้งหมดหรือไม่


5

ลองนำฟังก์ชั่นที่สามารถแทนค่าได้มาเป็นนิยามของ "คอนเทนเนอร์ขนาดคงที่":

class Representable f where
    type Rep f
    tabulate :: (Rep f -> a) -> f a
    index :: f a -> Rep f -> a

ความจริง Representableมีกฎหมายและซูเปอร์คลาสเพียงเล็กน้อย แต่สำหรับวัตถุประสงค์ของคำตอบนี้เราต้องการคุณสมบัติเพียงสองประการ:

tabulate . index = id
index . tabulate = id

(โอเคเราต้องปฏิบัติตามกฎหมายด้วย instance StrongApplicative ((->) r)เช่นกันง่าย ๆ คุณยอมรับแล้วว่ามันมีอยู่แล้ว)

หากเราใช้คำจำกัดความนั้นฉันสามารถยืนยันการคาดเดาที่ 1:

ทุกคนที่Applicativeเป็นตัวแทนของภาชนะ "ขนาดคงที่" ขององค์ประกอบของการโต้แย้งประเภทของมันเป็นตัวอย่าง [ปฏิบัติตามกฎหมาย] ของStrongApplicative

เป็นความจริง. นี่คือวิธี:

instance Representable f => Applicative f where
    zip (fa, fb) = tabulate (zip (index fa, index fb))
    husk = tabulate . husk

instance Representable f => OpApplicative f where
    unzip fab = let (fa, fb) = unzip (index fab) in (tabulate fa, tabulate fb)
    unhusk = unhusk . index

instance Representable f => StrongApplicative f

มีกฎหมายมากมายที่จะพิสูจน์ได้ แต่ฉันจะมุ่งเน้นไปที่บิ๊กโฟร์ที่StrongApplicativeเพิ่มเข้ามา - คุณอาจเชื่อแล้วว่าเป็นผู้นำในการทำธุรกิจApplicativeและOpApplicativeหากคุณไม่ทำข้อพิสูจน์ของพวกเขาดูเหมือนกับด้านล่าง ( ซึ่งจะมีลักษณะเหมือนกันมาก) เพื่อความชัดเจนผมจะใช้zipf, huskfและอื่น ๆ เช่นฟังก์ชั่นและzipr, huskrฯลฯ สำหรับอินสแตนซ์ที่แทนเพื่อให้คุณสามารถติดตามซึ่งเป็นที่ (และเพื่อให้ง่ายต่อการตรวจสอบว่าเราไม่ได้ใช้สิ่งที่เราพยายามพิสูจน์ว่าเป็นข้อสมมุติ! มันไม่เป็นไรที่จะใช้unhuskf . huskf = idเมื่อพิสูจน์unhuskr . huskr = idแต่มันจะผิดที่จะสันนิษฐานunhuskr . huskr = idในหลักฐานเดียวกัน)

การพิสูจน์ของกฎหมายแต่ละข้อนั้นดำเนินไปในลักษณะเดียวกันโดย: คำ จำกัด ความคลี่คลายวางแนวมอร์ฟิซึ่มที่Representableให้คุณแล้วใช้กฎแบบอะนาล็อกเพื่อทำหน้าที่

unhuskr . huskr
= { def. of unhuskr and huskr }
(unhuskf . index) . (tabulate . huskf)
= { index . tabulate = id }
unhuskf . huskf
= { unhuskf . huskf = id }
id

huskr . unhuskr
= { def. of huskr and unhuskr }
(tabulate . huskf) . (unhuskf . index)
= { huskf . unhuskf = id }
tabulate . index
= { tabulate . index = id }
id

zipr (unzipr fab)
= { def. of unzipr }
zipr (let (fa, fb) = unzipf (index fab) in (tabulate fa, tabulate fb))
= { def. of zipr }
let (fa, fb) = unzipf (index fab) in tabulate (zipf (index (tabulate fa), index (tabulate fb)))
= { index . tabulate = id }
let (fa, fb) = unzipf (index fab) in tabulate (zipf (fa, fb))
= { def. of (fa, fb) }
tabulate (zipf (unzipf (index fab)))
= { zipf . unzipf = id }
tabulate (index fab)
= { tabulate . index = id }
fab

unzipr (zipr (fa, fb))
= { def. of zipr }
unzipr (tabulate (zipf (index fa, index fb)))
= { def. of unzipr }
let (fa', fb') = unzipf (index (tabulate (zipf (index fa, index fb))))
in (tabulate fa', tabulate fb')
= { index . tabulate = id }
let (fa', fb') = unzipf (zipf (index fa, index fb))
in (tabulate fa', tabulate fb')
= { unzipf . zipf = id }
let (fa', fb') = (index fa, index fb)
in (tabulate fa', tabulate fb')
= { def. of fa' and fb' }
(tabulate (index fa), tabulate (index fb))
= { tabulate . index = id }
(fa, fb)

กำลังไตร่ตรองอยู่ในขณะนี้: instance StrongApplicative f => Representable f where type Rep f = forall x. f x -> x. indexมันง่าย. ฉันยังไม่ได้ใช้กลอุบายสำหรับtabulateแต่ดูเหมือนว่ายั่วเย้า
Daniel Wagner

ในการสนทนากับ @ AsadSaeeduddin ฉันสามารถค้นหาStrongApplicativeอินสแตนซ์เดียวกันนี้ได้เช่นกัน แต่ไม่สามารถพิสูจน์กฎหมายได้ ขอแสดงความยินดีที่ได้ทราบ! ฉันพยายามทำRepresentableตัวอย่างที่ให้StrongApplicativeมา แต่ไม่สามารถนึกถึงRepประเภทที่ดีได้- ฉันอยากรู้อยากเห็นคุณทำforall x. f x -> xสิ่งนี้ได้อย่างไร
bradrn

@ bradrn จำได้ว่าสมมติฐานคือสิ่งเหล่านี้มีชุด "หลุม" ที่คงที่ซึ่งช่ององค์ประกอบ จากนั้นฟังก์ชั่นของประเภทforall x. f x -> xคือฟังก์ชั่นที่เลือกหลุมและส่งกลับค่าในหลุมนั้น (และในขณะที่คิดเกี่ยวกับวิธีการใช้งานtabulateฉันได้สร้างข้อคัดค้านให้กับประเภทสำหรับunhuskดูความคิดเห็นเกี่ยวกับคำถามเพื่อดูรายละเอียด)
Daniel Wagner

ขอบคุณ @DanielWagner! นั่นเป็นวิธีที่ฉลาดจริงๆ - ฉันคงไม่คิดอย่างนั้น
bradrn

หลังจากที่พยายามที่จะใช้มันฉันไม่คิดว่าฉันเชื่อว่าจะทำงานเป็นforall x. f x -> x Repเหตุผลของฉันคือว่าใช้นี้Repคุณสามารถเขียนindexสำหรับการใด ๆชนิดไม่ได้เป็นเพียงStrongApplicativeคน - ดังนั้นฉันสงสัยว่าforall x. f x -> xอาจจะกว้างเกินไป
bradrn
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.