多参数类型同义词实例

时间:2013-04-17 12:24:17

标签: haskell typeclass

我正在试图弄清楚是否有可能(以及如何)为多参数类型同义词定义类实例。

例如:

{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}

type F a b = a -> b
data DF a b = DF (a -> b)

class C c a b where
    doc :: c a b -> a -> b

适用于多参数类型的实例:

instance C DF a b where
    doc (DF f) x = f x

但它不适用于类型同义词:

-- ERROR:
--
-- Type synonym `F' should have 2 arguments, but has been given none
-- In the instance declaration for `C F a b'
--
instance C F a b where
    doc f x = f x

是否可以为F

定义类型类实例

2 个答案:

答案 0 :(得分:16)

这不可能是书面的。类型同义词通常必须完全应用才能使用它们,尤其是as a type class parameter

请注意,如果您可以eta-reduce类型同义词,则可以使用实例;它是必须完全应用的同义词,而不是它所指的类型。所以这会奏效:

type F = (->)

instance C F a b where
    doc f x = f x

关于扩展类型同义词有a LiberalTypeSynonyms extension that relaxes some of the rules,但它在这里没有帮助 - 它只允许你做一些事情,比如将部分应用的类型同义词作为另一个类型同义词的类型参数。一切都必须完全扩展到其他方面。

要查看为什么需要此限制的一个原因,请考虑以下类型的同义词:

type Flip f a b = f b a

以下实例:

instance Functor (Flip Either a) where
    fmap _ (Right x) = Right x
    fmap f (Left x) = Left (f x)

回想一下,除了镜像之外,还有一个实例Functor (Either a)执行相同的操作。两者都是明智的Functor个实例。

请注意,与newtype不同,类型同义词被认为与它们引用的类型相同,表达式fmap not (Right True :: Either Bool Bool)的值应该是什么?

答案 1 :(得分:3)

必须完全应用类型同义词才能为它们定义实例。正如人们所期望的那样,F的类型不是* -> * -> *,而是在提供两个以上的类型参数之前无效。尝试

type F = (->)

代替。