如何在递归方案中派生实例 [英] How to derive instances in recursion schemes

查看:99
本文介绍了如何在递归方案中派生实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在测试这篇文章中的一些想法。

我想为Term类型派生一个Eq实例:

  { - #LANGUAGE DeriveFunctor# - } 
数据树a =分支Int [a] | Leaf Int派生(Eq,Functor,Show)
数据术语f = Term(f(Term f))派生(Eq)

但是得到这个错误:

 (Eq(f(Term f)) )
由'Term'的第一个字段(类型'f(Term f)')产生
可能的修复:
使用独立的派生实例声明
,所以你可以自己指定实例上下文
当为(Eq(Term f))派生实例时

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

  { - #LANGUAGE DeriveFunctor# - } 
{ - #LANGUAGE StandaloneDeriving # - }
数据树a =分支Int [a] | Leaf Int派生(Eq,Functor,Show)
数据Term f = Term(f(Term f))
导出实例(Eq f)=> Eq(Term f)

但是得到这个错误:

 'Term'的第一个参数应该有'*  - > *',
但'f'有种'*'
在'(Eq f)=>'的独立派生实例中,公式(Term f)'

现在我被卡住了。我如何显示f有一种 * - > * ?为什么我需要为 Term 但不是 Tree 的独立派生实例?两者都有类型变量,不一定会成为Eq的实例? ( a f

解决方案

有两种解决方案:

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

 派生实例(Eq(f(Term f) ))=> Eq(Term f)

这就是 recursion-schemes 在当然

-



或者,您可以使用 Eq1 来自 变形金刚 base-4.9.0.0



<$ p $其中
liftEq ::(a - > b - > Bool) - > f a - > f b - > Bool

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

实例Eq1 f => Eq(Term f)其中
Term a == Term b = eq1 ab

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


I am testing out some of the ideas in this article.

I want to derive an instance of Eq for the type Term:

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

But get this error:

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

I tried adding a standalone deriving instance:

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

But get this error:

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

Now I'm stuck. How do I show that f has a kind * -> *? And why do I need a standalone deriving instance for Term but not Tree? Both have type variables that are not necessarily going to be instances of Eq? (a and f)

解决方案

There are two solutions:

Using some GHC extensions StandaloneDeriving, UndecidableInstances and some others you can write:

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

This is what recursion-schemes does at the moment

--

Alternatively, you can use Eq1 from transformers or 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

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

这篇关于如何在递归方案中派生实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆