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

时间:2016-08-15 16:19:23

标签: haskell

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

我想为Term:

类型派生一个Eq实例
$("#datepicker").blur(function(){
        var date = $(this).datepicker('getDate')
        val = $(this).val();
       year =  date.getFullYear();
        val1 = Date.parse(val);
        if (year < 2016){
           alert("error")
        }
        else{
           console.log(val1);
        }
    });
});

但是得到这个错误:

{-# 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)

现在我被卡住了。如何显示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)’ 种类?为什么我需要* -> *而不是Term的独立派生实例?两者都有类型变量,不一定是Eq的实例? (Treea

1 个答案:

答案 0 :(得分:8)

有两种解决方案:

使用一些GHC扩展StandaloneDerivingUndecidableInstances和其他一些你可以写的:

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

这是recursion-schemes目前所做的事情

-

或者,您可以使用transformersEq1

中的base-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