专门为明确类型的参数提供功能

时间:2013-11-06 18:11:27

标签: haskell functional-dependencies

我想编写一个函数bar :: Foo a -> Foo b -> Foo c,这样如果ab属于同一类型,则c属于该类型,否则它是()。我怀疑功能依赖会对我有所帮助,但我不确定如何。我写了

class Bar a b c | a b -> c where
  bar :: Foo a -> Foo b -> Foo c 

instance Bar x x x where
  bar (Foo a) (Foo b) = Foo a

instance Bar x y () where
  bar _ _ = Foo ()

但显然,bar (Foo 'a') (Foo 'b')满足两个实例。我如何仅为两个不同类型x /= y声明一个实例?

1 个答案:

答案 0 :(得分:3)

你快到了。您可以使用OverlappingInstancesUndecidableInstances轻松完成此操作。由于这可能是一个封闭的世界类,不可判断的实例对你来说可能没什么大不了的。

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances
 , OverlappingInstances, TypeFamilies, UndecidableInstances #-}

data Foo a = Foo a deriving Show

class Bar a b c | a b -> c where
  bar :: Foo a -> Foo b -> Foo c 

instance Bar x x x where
  bar (Foo a) (Foo b) = Foo a

instance (u ~ ())=> Bar x y u where
  bar _ _ = Foo ()

注意最后一个实例:如果我们将()放在实例头中它变得比其他实例更具体并且首先匹配,所以我们改为使用类型相等断言TypeFamilies~)。我学到了这个from Oleg

请注意这种行为:

*Main> bar (Foo 'a') (Foo 'b')
Foo 'a'
*Main> bar (Foo 'a') (Foo True)
Foo ()
*Main> bar (Foo 'a') (Foo 1)

<interactive>:16:1:
    Overlapping instances for Bar Char b0 c0
      arising from a use of `bar'
    Matching instances:
      instance [overlap ok] u ~ () => Bar x y u
        -- Defined at foo.hs:13:10
      instance [overlap ok] Bar x x x -- Defined at foo.hs:9:10
    (The choice depends on the instantiation of `b0, c0'
     To pick the first instance above, use -XIncoherentInstances
     when compiling the other instance declarations)
    In the expression: bar (Foo 'a') (Foo 1)
    In an equation for `it': it = bar (Foo 'a') (Foo 1)

<interactive>:16:20:
    No instance for (Num b0) arising from the literal `1'
    The type variable `b0' is ambiguous
    Possible fix: add a type signature that fixes these type variable(s)
    Note: there are several potential instances:
      instance Num Double -- Defined in `GHC.Float'
      instance Num Float -- Defined in `GHC.Float'
      instance Integral a => Num (GHC.Real.Ratio a)
        -- Defined in `GHC.Real'
      ...plus three others
    In the first argument of `Foo', namely `1'
    In the second argument of `bar', namely `(Foo 1)'
    In the expression: bar (Foo 'a') (Foo 1)

同样在GHC 7.8中你可以访问封闭式家庭,我认为(希望,因为它与我的兴趣相关)将能够以更可口的方式处理这个问题,但细节得到{{3} }