本文介绍了无法在两个存在关于单身图书馆的情况下推论出KnownNat的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
{ - #LANGUAGE GADTs,StandaloneDeriving,RankNTypes,ScopedTypeVariables,
FlexibleInstances,KindSignatures,DataKinds,StandaloneDeriving# - }
导入Data.Singletons.Prelude
导入Data.Singletons.TypeLits
data Foo(a :: Nat)其中
Foo :: Foo a
派生显示
数据物件其中
Thing :: KnownNat a => ; Foo a - > Thing
导出实例Show Thing
afoo1 :: Foo 1
afoo1 = Foo
afoo2 :: Foo 2
afoo2 = Foo
athing :: Thing
athing = Thing afoo1
foolen :: forall n。 KnownNat n => Foo n - >整数
foolen foo =
唱歌(SNat :: Sing n) - > natVal(Proxy :: Proxy n)
minfoo :: forall a b c。 (Min a b_c,KnownNat c)=> Foo a - > Foo b - >整数
minfoo _ _ =
let c = case(SNat :: Sing c) - > natVal(Proxy :: Proxy c)
in natVal(Proxy :: Proxy c)
thinglen :: Thing - >整数
thinglen(Thing foo)= foolen foo
我可以用这个来得到最小值两件事
小事::物品 - >事情 - >整数
minthing(Thing foo1)(Thing foo2)= min(foolen foo1)(foolen foo2)
但为什么我不能这样做呢?
minthing':: Thing - >事情 - >整数
minthing'(Thing foo1)(Thing foo2)= minfoo foo1 foo2
•无法推断(KnownNat
(Data.Singletons.Prelude.Ord.Case_1627967386
a
a1
(Data.Singletons.Prelude.Ord.Case_1627967254
a a1(GHC.TypeLits.CmpNat a a1))))
解决方案
您需要做一些定理证明来检查给定 KnownNat a
和 KnownNat b
,您可以获得 KnownNat(Min ab)
。一个可能的解决方案:
$ p $ import Data.Constraint
(...)
定理:: forall a b。 (KnownNat a,KnownNat b)=>
唱歌 - > Sing b - > Dict(KnownNat(Min a b))
theorem sa sb = case sCompare sa sb of
SLT - > Dict
SEQ - >字典
SGT - >字典
fooSing :: forall a。 KnownNat a => Foo a - >唱一个
fooSing _ =唱歌
minthing':: Thing - >事情 - >整数
minthing'(Thing foo1)(Thing foo2)=
case theorem(fooSing foo1)(fooSing foo2)of
Dict - > minfoo foo1 foo2
I was experimenting with the singletons library and I found a case that I don't understand.
{-# LANGUAGE GADTs, StandaloneDeriving, RankNTypes, ScopedTypeVariables,
FlexibleInstances, KindSignatures, DataKinds, StandaloneDeriving #-}
import Data.Singletons.Prelude
import Data.Singletons.TypeLits
data Foo (a :: Nat) where
Foo :: Foo a
deriving Show
data Thing where
Thing :: KnownNat a => Foo a -> Thing
deriving instance Show Thing
afoo1 :: Foo 1
afoo1 = Foo
afoo2 :: Foo 2
afoo2 = Foo
athing :: Thing
athing = Thing afoo1
foolen :: forall n. KnownNat n => Foo n -> Integer
foolen foo =
case sing of (SNat :: Sing n) -> natVal (Proxy :: Proxy n)
minfoo :: forall a b c. (Min a b ~ c, KnownNat c) => Foo a -> Foo b -> Integer
minfoo _ _ =
let c = case sing of (SNat :: Sing c) -> natVal (Proxy :: Proxy c)
in natVal (Proxy :: Proxy c)
thinglen :: Thing -> Integer
thinglen (Thing foo) = foolen foo
I could use this to get the minimum of two Things
minthing :: Thing -> Thing -> Integer
minthing (Thing foo1) (Thing foo2) = min (foolen foo1) (foolen foo2)
But why can't I just do this?
minthing' :: Thing -> Thing -> Integer
minthing' (Thing foo1) (Thing foo2) = minfoo foo1 foo2
• Could not deduce (KnownNat
(Data.Singletons.Prelude.Ord.Case_1627967386
a
a1
(Data.Singletons.Prelude.Ord.Case_1627967254
a a1 (GHC.TypeLits.CmpNat a a1))))
解决方案
You need to do some theorem proving to check that given KnownNat a
and KnownNat b
you can get KnownNat (Min a b)
. A possible solution:
import Data.Constraint
(...)
theorem :: forall a b. (KnownNat a, KnownNat b) =>
Sing a -> Sing b -> Dict (KnownNat (Min a b))
theorem sa sb = case sCompare sa sb of
SLT -> Dict
SEQ -> Dict
SGT -> Dict
fooSing :: forall a. KnownNat a => Foo a -> Sing a
fooSing _ = sing
minthing' :: Thing -> Thing -> Integer
minthing' (Thing foo1) (Thing foo2) =
case theorem (fooSing foo1) (fooSing foo2) of
Dict -> minfoo foo1 foo2
这篇关于无法在两个存在关于单身图书馆的情况下推论出KnownNat的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!