1

我正在玩Data.Fixand Data.Functor.Sum,并尝试使用catasum 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
-}

首先,我有三个函ZeroSuccAdd。我使用Sum并定义了它们type Expr = Sum Zero (Sum Succ Add)

我还有Value将每个仿函数转换为数字的课程。由于我不想自己编写Valuefor的实例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 试过这个。

4

0 回答 0