2017-01-10 19 views
1

Похоже, что преобразования должны образовывать моноид, а функция идентификации как пустой элемент и стандартная функция - как двоичная операция. Я не думаю, что это особенно полезно, но это должно быть возможно. Что-то вдоль линий:Набор преобразований f :: a-> форма моноида над функцией композиции - как я могу сделать это экземпляром Monoid?

instance Monoid (a -> a) where 
     mempty = id 
     mappend f g = (.) 

Вышесказанное не обобщать, возможно, потому, что она маскируется ранее существовавшего определения

instance Monoid b => Monoid (a -> b) where 
    mempty _ = mempty 
    mappend f g x = f x `mappend` g x 

Ошибка:

Illegal instance declaration for ‘Monoid (a -> a)’ 
     (All instance types must be of the form (T a1 ... an) 
     where a1 ... an are *distinct type variables*, 
     and each type variable appears at most once in the instance head. 
     Use FlexibleInstances if you want to disable this.) 
    In the instance declaration for ‘Monoid (a -> a)’ 

Я m все еще сглаз Haskell, поэтому я не уверен, как я могу это исправить - любая помощь?

+2

В качестве примечания к ответам в дубликате, один пример отличного использования 'Endo' находится в [получении реализации по умолчанию для' foldr' из 'foldMap'] (http://stackoverflow.com/д/23319683/2751851). – duplode

ответ

2

Фактически сообщение об ошибке описывает это очень хорошо: a -> a это слишком специфический тип:

Все типы экземпляра должны иметь форму (T a1 ... an) где a1 ... an являются различные переменные типа, и каждая переменная типа появляется не более одного раза в голове экземпляра.

T здесь есть функция типа ->, вы могли бы написать без специальной инфиксной записи

instance Monoid ((->) a a) where … 

и четко a не только один раз.

О том, как это исправить, снова появляется сообщение об ошибке рекомендует

Используйте FlexibleInstances, если вы хотите отключить эту [ограничение].

+1

Или используйте 'TypeFamilies' и напишите' instance a ~ b => Monoid (a -> b) '. –