সম্পূর্ণরূপে নির্ভরশীল যুক্তি তৈরি করা


10

কনটেন্টেশন সম্পর্কে একটি দুর্দান্ত সত্য ঘটনাটি হ'ল যদি আমি সমীকরণের কোনও দুটি ভেরিয়েবল জানি:

a ++ b = c

তখন আমি তৃতীয়টি জানি।

আমি এই ধারণাটি আমার নিজস্ব উপসংগে ক্যাপচার করতে চাই তাই আমি কার্যকরী নির্ভরতা ব্যবহার করি।

{-# Language DataKinds, GADTs, FlexibleContexts, FlexibleInstances, FunctionalDependencies, KindSignatures, PolyKinds, TypeOperators, UndecidableInstances #-}
import Data.Kind (Type)

class Concatable
   (m  :: k -> Type)
   (as :: k)
   (bs :: k)
   (cs :: k)
   | as bs -> cs
   , as cs -> bs
   , bs cs -> as
   where
     concat' :: m as -> m bs -> m cs

এখন আমি এই জাতীয় মতবিরোধী তালিকা জালিয়াতি করছি:

data HList ( as :: [ Type ] ) where
  HEmpty :: HList '[]
  HCons  :: a -> HList as -> HList (a ': as)

কিন্তু যখন আমি এগুলি প্রকাশ করার চেষ্টা করি তখন আমার Concatableএকটি সমস্যা আছে

instance Concatable HList '[] bs bs where
  concat' HEmpty bs = bs
instance
  ( Concatable HList as bs cs
  )
    => Concatable HList (a ': as) bs (a ': cs)
  where
    concat' (HCons head tail) bs = HCons head (concat' tail bs)

আমি আমার তৃতীয় কার্যক্ষম নির্ভরতা সন্তুষ্ট করি না। অথবা বরং সংকলক বিশ্বাস করে যে আমরা তা করি না। এটি কারণ কারণ সংকলক বিশ্বাস করে যে আমাদের দ্বিতীয় উদাহরণে এটি হতে পারে bs ~ (a ': cs)। এবং যদি এটি হতে পারে Concatable as (a ': cs) cs

আমি কীভাবে আমার দৃষ্টান্তগুলি সামঞ্জস্য করতে পারি যাতে তিনটি নির্ভরতা সন্তুষ্ট হয়?


1
মূল সমস্যাটি মনে হচ্ছে bs cs -> as, কারণ আমাদের সম্পর্কে স্থানীয় bsএবং অদ্বিতীয় বা নীল হওয়া উচিত csকিনা তা নির্ধারণের জন্য স্থানীয় তথ্য প্রয়োজন as। কীভাবে এই তথ্য উপস্থাপন করবেন তা আমাদের খুঁজে বের করতে হবে; সরাসরি অনুমান করা যায় না, তখন আমরা গ্যারান্টি দেওয়ার জন্য কোনও প্রকারের স্বাক্ষরে কী যুক্ত করব?
লুচি

3
প্রসারিত করতে কি luqui বললঃ কল্পনা আমরা জানি bsএবং cs, এবং আমরা fundep কাজে লাগান করতে চান, অর্থাত আমরা পুনর্গঠন করতে চান as। এটি একটি নির্বিচারে পদ্ধতিতে করতে, আমরা আশা করি যে কোনও একক প্রতিশ্রুতিবদ্ধ এবং সেই রেসিপিটি অনুসরণ করতে সক্ষম হব। কংক্রিটলি, ধরে নিও bs = (Int ': bs2)এবং cs = (Int ': cs2)। আমরা কোন উদাহরণটি বেছে নেব? এটা সম্ভব যে এই ধরনের হয় Intমধ্যে csথেকে আসে bs(এবং asখালি)। asপরিবর্তে (অমানবিক) থেকে আসা এটিও সম্ভব Intএবং csপরে এটি আবার উপস্থিত হবে । আমাদের আরও গভীরভাবে খনন csকরতে হবে এবং জিএইচসি তা করবে না।
চি

1
মোটামুটিভাবে বলতে গেলে, জিএইচসি উদাহরণস্বরূপ ফান্ডেপগুলি গ্রহণ করবে যা উদাহরণস্বরূপ একটি সহজ রূপ অন্তর্ভুক্ত করে প্রমাণ করা যায়। এখানে, তাদের মধ্যে একটির প্রমানের জন্য এক ধরণের ডাবল আনয়ন প্রয়োজন (বা তাই এটি মনে হয়), এবং সংকলকটি এতদূর যায় না।
চি

উত্তর:


10

সুতরাং, মতামত অনুসারে, জিএইচসি এটি নিজের মতো করে বের করে আনবে না, তবে আমরা একে একে টাইপ লেভেল প্রোগ্রামিংয়ের সাহায্য করতে পারি। আসুন কিছু পরিচয় করিয়ে দেওয়া যাক TypeFamilies। এই সমস্ত ফাংশন হ'ল ধরণের স্তরের উপরে তোলা তালিকার ম্যানিপুলেশনের বেশ সোজা অনুবাদ:

-- | This will produce the suffix of `cs` without `as`
type family DropPrefix (as :: [Type]) (cs :: [Type]) where
  DropPrefix '[] cs = cs
  DropPrefix (a ': as) (a ': cs) = DropPrefix as cs

-- Similar to the logic in the question itself: list concatenation. 
type family Concat (as :: [Type]) (bs :: [Type]) where
  Concat '[] bs = bs
  Concat (head ': tail) bs = head ': Concat tail bs

-- | Naive list reversal with help of concatenation.
type family Reverse (xs :: [Type]) where
  Reverse '[] = '[]
  Reverse (x ': xs) = Concat (Reverse xs) '[x]

-- | This will produce the prefix of `cs` without `bs`
type family DropSuffix (bs :: [Type]) (cs :: [Type]) where
  DropSuffix bs cs = Reverse (DropPrefix (Reverse bs) (Reverse cs))

-- | Same definition of `HList` as in the question
data HList (as :: [Type]) where
  HEmpty :: HList '[]
  HCons :: a -> HList as -> HList (a ': as)

-- | Definition of concatenation at the value level
concatHList :: (cs ~ Concat as bs) => HList as -> HList bs -> HList cs
concatHList HEmpty bs = bs
concatHList (HCons head tail) bs = HCons head (concatHList tail bs)

আমাদের নিষ্পত্তির এই সরঞ্জামগুলির সাহায্যে আমরা আসলে ঘন্টাের লক্ষ্যে পৌঁছতে পারি তবে প্রথমে পছন্দসই বৈশিষ্ট্যগুলি সহ একটি ফাংশন সংজ্ঞায়িত করতে পারি:

  • csথেকে asএবং অনুমান করার ক্ষমতাbs
  • asথেকে bsএবং অনুমান করার ক্ষমতাcs
  • bsথেকে asএবং অনুমান করার ক্ষমতাcs

voila:

concatH ::
     (cs ~ Concat as bs, bs ~ DropPrefix as cs, as ~ DropSuffix bs cs)
  => HList as
  -> HList bs
  -> HList cs
concatH = concatHList

আসুন এটি পরীক্ষা করুন:

foo :: HList '[Char, Bool]
foo = HCons 'a' (HCons True HEmpty)

bar :: HList '[Int]
bar = HCons (1 :: Int) HEmpty
λ> :t concatH foo bar
concatH foo bar :: HList '[Char, Bool, Int]
λ> :t concatH bar foo
concatH bar foo :: HList '[Int, Char, Bool]

এবং অবশেষে শেষ লক্ষ্য:

class Concatable (m :: k -> Type) (as :: k) (bs :: k) (cs :: k)
  | as bs -> cs
  , as cs -> bs
  , bs cs -> as
  where
  concat' :: m as -> m bs -> m cs

instance (cs ~ Concat as bs, bs ~ DropPrefix as cs, as ~ DropSuffix bs cs) =>
         Concatable HList as bs cs where
  concat' = concatH
λ> :t concat' HEmpty bar
concat' HEmpty bar :: HList '[Int]
λ> :t concat' foo bar
concat' foo bar :: HList '[Char, Bool, Int]
λ> :t concat' bar foo
concat' bar foo :: HList '[Int, Char, Bool]

3
সাবাশ! এমনকি আমি সন্দেহ করেছিলাম এটি অসম্ভব হতে পারে তবে আপনি এটি স্বচ্ছ এবং মার্জিতভাবে সমাধান করেছেন।
লুচি

আপনাকে ধন্যবাদ, @ এলকুই
লেহিন্স
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.