আমি সম্প্রতি জানতে পেরেছি যে প্রুফের সাথে প্যাটার্ন মিলের সাথে মিলিত ধরণের গর্তগুলি হাসকেলে একটি দুর্দান্ত সুন্দর আগদার মতো অভিজ্ঞতা সরবরাহ করে। উদাহরণ স্বরূপ:
{-# LANGUAGE
DataKinds, PolyKinds, TypeFamilies,
UndecidableInstances, GADTs, TypeOperators #-}
data (==) :: k -> k -> * where
Refl :: x == x
sym :: a == b -> b == a
sym Refl = Refl
data Nat = Zero | Succ Nat
data SNat :: Nat -> * where
SZero :: SNat Zero
SSucc :: SNat n -> SNat (Succ n)
type family a + b where
Zero + b = b
Succ a + b = Succ (a + b)
addAssoc :: SNat a -> SNat b -> SNat c -> (a + (b + c)) == ((a + b) + c)
addAssoc SZero b c = Refl
addAssoc (SSucc a) b c = case addAssoc a b c of Refl -> Refl
addComm :: SNat a -> SNat b -> (a + b) == (b + a)
addComm SZero SZero = Refl
addComm (SSucc a) SZero = case addComm a SZero of Refl -> Refl
addComm SZero (SSucc b) = case addComm SZero b of Refl -> Refl
addComm sa@(SSucc a) sb@(SSucc b) =
case addComm a sb of
Refl -> case addComm b sa of
Refl -> case addComm a b of
Refl -> Refl
সত্যিই দুর্দান্ত জিনিসটি হ'ল আমি Refl -> exp
নির্মাণের ডান হাতের প্রকারগুলি একটি টাইপ গর্ত দিয়ে প্রতিস্থাপন করতে পারি এবং আমার গর্তের rewrite
লক্ষ্যগুলি প্রুফের সাথে আপডেট করা হয়, আগদার ফর্মের মতোই ।
তবে, মাঝে মাঝে গর্তটি আপডেট হতে ব্যর্থ হয়:
(+.) :: SNat a -> SNat b -> SNat (a + b)
SZero +. b = b
SSucc a +. b = SSucc (a +. b)
infixl 5 +.
type family a * b where
Zero * b = Zero
Succ a * b = b + (a * b)
(*.) :: SNat a -> SNat b -> SNat (a * b)
SZero *. b = SZero
SSucc a *. b = b +. (a *. b)
infixl 6 *.
mulDistL :: SNat a -> SNat b -> SNat c -> (a * (b + c)) == ((a * b) + (a * c))
mulDistL SZero b c = Refl
mulDistL (SSucc a) b c =
case sym $ addAssoc b (a *. b) (c +. a *. c) of
-- At this point the target type is
-- ((b + c) + (n * (b + c))) == (b + ((n * b) + (c + (n * c))))
-- The next step would be to update the RHS of the equivalence:
Refl -> case addAssoc (a *. b) c (a *. c) of
Refl -> _ -- but the type of this hole remains unchanged...
এছাড়াও, যদিও লক্ষ্যের প্রকারগুলি অগত্যা প্রমাণের মধ্যে সরে না যায়, যদি আমি আগদা থেকে পুরো জিনিসটি পেস্ট করি তবে এটি জরিমানা পরীক্ষা করে:
mulDistL' :: SNat a -> SNat b -> SNat c -> (a * (b + c)) == ((a * b) + (a * c))
mulDistL' SZero b c = Refl
mulDistL' (SSucc a) b c = case
(sym $ addAssoc b (a *. b) (c +. a *. c),
addAssoc (a *. b) c (a *. c),
addComm (a *. b) c,
sym $ addAssoc c (a *. b) (a *. c),
addAssoc b c (a *. b +. a *. c),
mulDistL' a b c
) of (Refl, Refl, Refl, Refl, Refl, Refl) -> Refl
কেন এমনটি হয় (বা আমি কীভাবে প্রুফ রাইটিংয়ে প্রবলভাবে লিখতে পারি) আপনার কি কোনও ধারণা আছে?
sym
কলগুলি বাদ দিতে পারেনmulDistL'
এবং আপনার কোডটি এখনও পরীক্ষা করে রাখতে পারে।