我正在玩Data.Fix
and Data.Functor.Sum
,并尝试使用cata
sum of functors,然后遇到了代码没有类型检查的问题。但我不确定如何进行类型检查。
这是代码。
{-# 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 Succ Add)
。
我还有Value
将每个仿函数转换为数字的课程。由于我不想自己编写Value
for的实例Sum
,所以我介绍IsPartOf
了知道如何构造函子之和 ( inj
) 以及如何将内部函子的函数应用于外部函子 ( app
) 的类。
但是当我尝试使用它们时cata (app value) (succ zero)
,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)
为什么 GHC 找不到合适的实例?我怎样才能进行这种类型检查,或者什么是表达这个想法的正确方法?
我用 GHC 7.10.3 试过这个。