2013-04-17 2 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 = (->) 

вместо этого.

Смежные вопросы