Haskell 使用带有函子和的cata

Haskell 使用带有函子和的cata,haskell,recursion-schemes,Haskell,Recursion Schemes,我在玩and,并尝试使用和函子,然后遇到了一个代码没有进行类型检查的问题。但我不知道如何才能进行型式检验 *Main> cata (app value) (succ zero) <interactive>:10:7: Overlapping instances for IsPartOf f0 Expr arising from a use of ‘app’ Matching instances: instance [overlappab

我在玩and,并尝试使用和函子,然后遇到了一个代码没有进行类型检查的问题。但我不知道如何才能进行型式检验

*Main> cata (app value) (succ zero)

<interactive>:10:7:
    Overlapping instances for IsPartOf f0 Expr
      arising from a use of ‘app’
    Matching instances:
      instance [overlappable] (Functor f, Functor g, Functor h,
                               IsPartOf f g) =>
                              IsPartOf f (Sum h g)
        -- Defined at min.hs:16:31
      instance [overlappable] Functor f => IsPartOf f f
        -- Defined at min.hs:10:31
      instance [overlappable] (Functor f, Functor g) =>
                              IsPartOf f (Sum f g)
        -- Defined at min.hs:13:31
    (The choice depends on the instantiation of ‘f0’
     To pick the first instance above, use IncoherentInstances
     when compiling the other instance declarations)
    In the first argument of ‘cata’, namely ‘(app value)’
    In the expression: cata (app value) (succ zero)
    In an equation for ‘it’: it = cata (app value) (succ zero)

<interactive>:10:11:
    Could not deduce (Value f0) arising from a use of ‘value’
    from the context (Num a)
      bound by the inferred type of it :: Num a => a
      at <interactive>:10:1-28
    The type variable ‘f0’ is ambiguous
    Note: there are several potential instances:
      instance Value Add -- Defined at min.hs:41:10
      instance Value Succ -- Defined at min.hs:39:10
      instance Value Zero -- Defined at min.hs:37:10
    In the first argument of ‘app’, namely ‘value’
    In the first argument of ‘cata’, namely ‘(app value)’
    In the expression: cata (app value) (succ zero)
这是代码

{-# LANGUAGE DeriveFunctor, FlexibleInstances, MultiParamTypeClasses #-}

import Data.Fix (Fix(Fix), cata)
import Data.Functor.Sum (Sum(InL, InR))
import Prelude hiding (succ)

class (Functor f, Functor g) => IsPartOf f g where
    inj :: f a -> g a
    app :: (f a -> a) -> (g a -> a)
instance {-# OVERLAPPABLE #-} Functor f => IsPartOf f f where
    inj = id
    app = id
instance {-# OVERLAPPABLE #-} (Functor f, Functor g) => IsPartOf f (Sum f g) where
    inj = InL
    app f (InL l) = f l
instance {-# OVERLAPPABLE #-} (Functor f, Functor g, Functor h, IsPartOf f g) => IsPartOf f (Sum h g) where
    inj = InR . inj
    app f (InR r) = app f r

data Zero e = Zero deriving Functor
data Succ e = Succ e deriving Functor
data Add e = Add e e deriving Functor

type Expr = Sum Zero (Sum Succ Add)

zero :: Fix Expr
zero = Fix (inj Zero)

succ :: Fix Expr -> Fix Expr
succ = Fix . inj . Succ

add :: Fix Expr -> Fix Expr -> Fix Expr
add = ((Fix . inj) .) . Add

class Value f where
    value :: Num a => f a -> a
instance Value Zero where
    value _ = 0
instance Value Succ where
    value (Succ e) = 1 + e
instance Value Add where
    value (Add e1 e2) = e1 + e2
{-
instance (Value f, Value g) => Value (Sum f g) where
    value (InL f) = value f
    value (InR g) = value g
-}
首先,我有三个函子
Zero
Succ
Add
。我使用
Sum
组合了它们,并定义了
type Expr=Sum Zero(Sum such Add)

我还有
Value
类将每个函子转换成一个数字。因为我不想自己为
Sum
编写
Value
的实例,所以我引入了
IsPartOf
类,它知道如何构造一个和的函子(
inj
),以及如何将一个内部函子的函数应用于一个外部函子(
app

但当我尝试使用它们时,比如
cata(appvalue)(succzero)
,GHC说它不进行类型检查

*Main> cata (app value) (succ zero)

<interactive>:10:7:
    Overlapping instances for IsPartOf f0 Expr
      arising from a use of ‘app’
    Matching instances:
      instance [overlappable] (Functor f, Functor g, Functor h,
                               IsPartOf f g) =>
                              IsPartOf f (Sum h g)
        -- Defined at min.hs:16:31
      instance [overlappable] Functor f => IsPartOf f f
        -- Defined at min.hs:10:31
      instance [overlappable] (Functor f, Functor g) =>
                              IsPartOf f (Sum f g)
        -- Defined at min.hs:13:31
    (The choice depends on the instantiation of ‘f0’
     To pick the first instance above, use IncoherentInstances
     when compiling the other instance declarations)
    In the first argument of ‘cata’, namely ‘(app value)’
    In the expression: cata (app value) (succ zero)
    In an equation for ‘it’: it = cata (app value) (succ zero)

<interactive>:10:11:
    Could not deduce (Value f0) arising from a use of ‘value’
    from the context (Num a)
      bound by the inferred type of it :: Num a => a
      at <interactive>:10:1-28
    The type variable ‘f0’ is ambiguous
    Note: there are several potential instances:
      instance Value Add -- Defined at min.hs:41:10
      instance Value Succ -- Defined at min.hs:39:10
      instance Value Zero -- Defined at min.hs:37:10
    In the first argument of ‘app’, namely ‘value’
    In the first argument of ‘cata’, namely ‘(app value)’
    In the expression: cata (app value) (succ zero)
*Main>cata(应用程序值)(成功归零)
:10:7:
iPartof f0 Expr的重叠实例
因使用“应用程序”而产生
匹配实例:
实例[可重叠](函子f,函子g,函子h,
IsPartOf f g)=>
i部分f(总和h g)
--在最小值时定义:16:31
实例[overlappable]函子f=>IsPartOf f
--最小时的定义:10:31
实例[可重叠](函子f,函子g)=>
i部分f(总和f g)
--在最小值时定义:13:31
(选择取决于“f0”的实例化
要选择上面的第一个实例,请使用不连贯
编译其他实例声明时)
在'cata'的第一个参数中,即'app value'
表达式中:cata(应用值)(成功零)
在“it”的方程式中:it=cata(应用值)(成功为零)
:10:11:
无法推断因使用“Value”而产生的(值f0)
从上下文(Num a)
由它的推断类型绑定::Num a=>a
时间:10:1-28
类型变量“f0”不明确
注意:有几个潜在的例子:
实例值添加--在min.hs:41:10处定义
实例值Succ--在min.hs:39:10处定义
实例值零——定义为min.hs:37:10
在'app'的第一个参数中,即'value'
在'cata'的第一个参数中,即'app value'
表达式中:cata(应用值)(成功零)
为什么GHC找不到合适的实例?我如何进行这种类型检查,或者什么是表达这种想法的正确方式


我在GHC 7.10.3中尝试过这一点。

编译器说
选择取决于'f0'的实例化。
。您使用的
value
类型为
(value f,Num a)=>fa->a
,没有提示应该使用
应用程序的哪个实现。分散一些类型注释在那里,你应该很好去。谢谢你的评论。现在我想我明白了。我无法为
cata(app value)(succ zero)
中的
value
提供类型注释,因为
Expr
不是
value
的实例,不像我可以做
cata(app(value::Num a=>zero a->a))(Fix zero)
。因此,我在这里试图为
Expr
自动定义
Value
的实例。我想我可以用TH来做,但是没有TH有什么方法可以做吗?等等,为什么你不能写呢?看起来对我来说是正确的。你的意思是我可以写
cata(app(value::Num a=>Expr a->a))(succ zero)
?是的,它没有键入check。编译器说
选择取决于'f0'的实例化。
。您使用的
value
类型为
(value f,Num a)=>fa->a
,没有提示应该使用
应用程序的哪个实现。分散一些类型注释在那里,你应该很好去。谢谢你的评论。现在我想我明白了。我无法为
cata(app value)(succ zero)
中的
value
提供类型注释,因为
Expr
不是
value
的实例,不像我可以做
cata(app(value::Num a=>zero a->a))(Fix zero)
。因此,我在这里试图为
Expr
自动定义
Value
的实例。我想我可以用TH来做,但是没有TH有什么方法可以做吗?等等,为什么你不能写呢?看起来对我来说是正确的。你的意思是我可以写
cata(app(value::Num a=>Expr a->a))(succzero)
?是的,它没有键入check。