2013-04-17 76 views
10

我想知道是否有可能(以及如何)爲多參數類型同義詞定義類實例。多參數類型同義詞實例

例如:

{-# 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定義一個類型類實例嗎?

回答

14

這是不可能的書面。類型同義詞通常必須完全適用於使用它們,尤其是as a type class parameter

請注意,如果您可以eta-減少類型的同義詞足夠一個實例是可能的;它是必須完全應用的同義詞,而不是它所指的類型。因此,這會工作:

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)的值應該是什麼?

3

類型同義詞必須完全適用於可以爲其定義的實例。正如人們所預料的那樣,F的類型不是* -> * -> *,而是直到提供了兩個更多的類型參數纔會失效。嘗試

type F = (->) 

改爲。

相關問題