任何人都知道如何/ this code可以延长Foo
GADT:
{-# language GADTs #-}
{-# language DeriveGeneric #-}
{-# language DeriveAnyClass #-}
{-# language TemplateHaskell #-}
{-# language StandaloneDeriving #-}
import Prelude (Int, String, print, ($))
import Data.GADT.Show ()
import Data.GADT.Compare ()
import Data.Dependent.Map (DMap, fromList, (!))
import Data.Dependent.Sum ((==>))
import Data.GADT.Compare.TH (deriveGEq, deriveGCompare)
import Data.Functor.Identity (Identity)
data Foo a where
AnInt :: Foo Int
AString :: Foo String
deriveGEq ''Foo
deriveGCompare ''Foo
dmap1 :: DMap Foo Identity
dmap1 = fromList [AnInt ==> 1, AString ==> "bar"]
main = do
print $ dmap1 ! AnInt
print $ dmap1 ! AString
-- Prints:
-- Identity 1
-- Identity "bar"
与
ANum :: Num n => Foo n
(或类似的东西)允许dependent-map
中的多态值?
当我尝试时,我得到类似的错误:
exp-dep-map.hs:20:1: error:
• Couldn't match type ‘a’ with ‘b’
‘a’ is a rigid type variable bound by
the type signature for:
geq :: forall a b. Foo a -> Foo b -> Maybe (a := b)
at exp-dep-map.hs:20:1-20
‘b’ is a rigid type variable bound by
the type signature for:
geq :: forall a b. Foo a -> Foo b -> Maybe (a := b)
at exp-dep-map.hs:20:1-20
Expected type: Maybe (a := b)
Actual type: Maybe (a :~: a)
• In a stmt of a 'do' block: return Refl
In the expression: do return Refl
In an equation for ‘geq’: geq ANum ANum = do return Refl
• Relevant bindings include
geq :: Foo a -> Foo b -> Maybe (a := b)
(bound at exp-dep-map.hs:20:1)
|
20 | deriveGEq ''Foo
| ^^^^^^^^^^^^^^^^^^^^
编辑:我已经与echatav和isovector(GitHub用户名)一起继续努力,我们能够进一步解决这个问题,我们还发现定义GEq
和{{1}用手帮助实例。谢谢你,@ rampion,你的回答也证实了我们所发现的。
虽然为大型记录类型手动定义这些并不理想。我想知道TemplateHaskell生成器(GCompare
,deriveGCompare
){是否需要}可以更新以处理多态性。
此外,我发现,对于我目前的用例,我正在寻找的pol实际上更接近
deriveGEq
手动定义实例也适用于此,而且不太理想。
data Foo n a where
AnInt :: Foo n Int
AString :: Foo n String
ANum :: (Num n, Typeable n, Show n) => Foo n n
尝试使用TH,(例如instance GEq (Foo n) where
geq AnInt AnInt = return Refl
geq AString AString = return Refl
geq ANum ANum = return Refl
geq _ _ = Nothing
instance GCompare (Foo n) where
gcompare AnInt AnInt = GEQ
gcompare AnInt _ = GLT
gcompare _ AnInt = GGT
gcompare AString AString = GEQ
gcompare AString _ = GLT
gcompare _ AString = GGT
gcompare (ANum :: Foo n a) (ANum :: Foo n b) = (eqT @a @b) & \case
Just (Refl :: a :~: b) -> GEQ
Nothing -> error "This shouldn't happen"
gcompare ANum _ = GLT
gcompare _ ANum = GGT
或deriveGEq ''Foo
)我遇到了问题。
deriveGEq ''(Foo n)
exp-dep-map.hs:39:1: error:
• Expecting one more argument to ‘Foo’
Expected kind ‘* -> *’, but ‘Foo’ has kind ‘* -> * -> *’
• In the first argument of ‘GEq’, namely ‘Foo’
In the instance declaration for ‘GEq Foo’
|
39 | deriveGEq ''Foo
| ^^^^^^^^^^^^^^^^^^^^
也许相关:https://github.com/mokus0/dependent-sum-template/pull/6
答案 0 :(得分:5)
模板haskell让我很难看到发生了什么,所以我建议你推出自己的GEq
实例来更好地理解错误。
class GEq f where
geq :: f a -> f b -> Maybe (a := b)
我们对a
或b
没有任何进一步的限制,所以我们需要单独证明(或反驳)GADT构造函数上的类型相等。
以上ANum
未提供给我们。
如果我们向ANum
添加另一个约束 - Typeable
ANum :: (Num n, Typeable n) => n -> Foo n
现在我们可以使用eqT
来见证类型相等
geq (ANum _) (ANum _) = eqT