haskell - 如何在递归方案中派生实例

标签 haskell

我正在测试 this article 中的一些想法.

我想派生 Term 类型的 Eq 实例:

{-# LANGUAGE DeriveFunctor #-}
data Tree a = Branch Int [a] | Leaf Int deriving (Eq, Functor, Show)
data Term f = Term (f (Term f)) deriving (Eq)

但出现此错误:

No instance for (Eq (f (Term f)))
      arising from the first field of ‘Term’ (type ‘f (Term f)’)
    Possible fix:
      use a standalone 'deriving instance' declaration,
        so you can specify the instance context yourself
    When deriving the instance for (Eq (Term f))

我尝试添加一个独立的派生实例:

{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE StandaloneDeriving #-}
data Tree a = Branch Int [a] | Leaf Int deriving (Eq, Functor, Show)
data Term f = Term (f (Term f))
deriving instance (Eq f) => Eq (Term f)

但出现此错误:

The first argument of ‘Term’ should have kind ‘* -> *’,
  but ‘f’ has kind ‘*’
In the stand-alone deriving instance for ‘(Eq f) => Eq (Term f)’

现在我被困住了。如何证明 f 有一种 * -> *?为什么我需要 Term 的独立派生实例而不是 Tree?两者都有类型变量,这些变量不一定是 Eq? 的实例。 (af)

最佳答案

有两种解决方案:

使用一些 GHC 扩展 StandaloneDerivingUndecidableInstances 以及其他一些您可以编写的扩展:

deriving instance (Eq (f (Term f))) => Eq (Term f)

这就是 recursion-schemes目前做

--

或者,您可以使用 transformers 中的 Eq1base-4.9.0.0

class Eq1 f where
    liftEq :: (a -> b -> Bool) -> f a -> f b -> Bool

eq1 :: (Eq1 f, Eq a) -> f a -> f a -> Bool
eq1 = liftEq (==)

instance Eq1 f => Eq (Term f) where
    Term a == Term b = eq1 a b

引用:https://github.com/ekmett/recursion-schemes/blob/ffada24f92efd5bcfe71f7f0af3b4af057f50bd0/Data/Functor/Foldable.hs#L392

关于haskell - 如何在递归方案中派生实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38958895/

相关文章:

python - 为什么我翻译成 Python 的 Haskell 不能正常工作?

postgresql - 对 Hasql 查询的参数列表进行编码

parsing - Haskell 无法读取这个 double : ".3". 这是一个错误吗?

haskell - 在 Haskell 中,如何生成完美平衡的二叉搜索树?

haskell - Applicative 的 ghci 特例?

haskell - react 香蕉 : how to use values from a remote API and merge them in the event stream

function - Haskell 程序的基本结构

haskell - 如何让函数返回不同的类型

haskell - 折叠函数不断切换var位置

haskell - 将功能依赖类转换为类型族实例