gpt4 book ai didi

haskell - (如何)在 `dependent-map` GADT 中可能具有多态值?

转载 作者:行者123 更新时间:2023-12-01 11:16:36 28 4
gpt4 key购买 nike

任何人都知道如何/是否可以扩展 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手动 GCompare 实例有帮助。所以谢谢你,@rampion,你的回答也证实了我们的发现。

尽管为大型记录类型手动定义这些并不理想。我想知道 TemplateHaskell 生成器(deriveGComparederiveGEq)是否{需要、可能}更新以处理多态性。

此外,我发现对于我当前的用例,我正在寻找的 pol'ism 实际上更接近

data Foo n a where
AnInt :: Foo n Int
AString :: Foo n String
ANum :: (Num n, Typeable n, Show n) => Foo n n

手动定义的实例在这里也适用,但又不太理想。

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

尝试使用 TH,(例如 deriveGEq ''FooderiveGEq ''(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
| ^^^^^^^^^^^^^^^^^^^^

exp-dep-map.hs:40:19: error: parse error on input ‘Foo’
|
40 | deriveGEq ''(Foo n)
| ^^^

可能相关:https://github.com/mokus0/dependent-sum-template/pull/6

最佳答案

模板 haskell 很难看出发生了什么,所以我建议您滚动自己的 GEq 实例以更好地理解错误。

the definition of GEq :

class GEq f where
geq :: f a -> f b -> Maybe (a := b)

我们对 ab 没有任何进一步的限制,因此我们需要单独证明(或反驳)GADT 构造函数的类型相等性。

上面的 ANum 没有给我们。

不过,如果我们向 ANum 添加另一个约束 - Typeable

,这是可以解决的
ANum :: (Num n, Typeable n) => n -> Foo n

现在我们可以使用eqT见证类型平等

geq (ANum _) (ANum _) = eqT

关于haskell - (如何)在 `dependent-map` GADT 中可能具有多态值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50048842/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com