2012-03-07 3 views
4

Есть ли способ дальнейшего ограничения контекста существующего класса типа?Howto дополнительно ограничивает существующий класс типа в Haskell

Например, тип класса Functor:

class Functor f where 
    fmap :: (a -> b) -> f a -> f b 

Это определение класса не обеспечивает a или b, чтобы быть элементом Show. Также этот тип класса является классом, который включен мной, поэтому я не могу повлиять на определение классов. Возможно ли, что позже разрешите только a и что b, которые являются членами Show?

+0

Было бы очень интересно услышать, почему вы хотите иметь искусственные ограничения не оправдываются кодом. Возможно, есть недоразумения, которые могут быть решены. – Ingo

+0

Ограничения обычно помещаются на функции, а не на данные/типы. Причина в том, что вы никогда не узнаете, что вам нужно. Допустим, вы используете «ShowFunctor» от Daniel. Вы не можете сделать его аппликативным (и, следовательно, монадой), потому что аппликаторы должны иметь возможность обертывания функций, а функция не имеет экземпляра show. – mb14

ответ

10

Не напрямую. Определение класса не может быть изменено без изменения источника и перекомпиляции. В случае классов, определенных в стандартных библиотеках, это вызовет многократное нарушение кода, поэтому не является реалистичным вариантом.

Однако вы можете обернуть класс и добавить желаемые ограничения,

class Functor f => ShowFunctor f where 
    smap :: (Show a, Show b) => (a -> b) -> f a -> f b 
    smap f = fmap f 

, а затем использовать этот класс вместо оригинала.

Но, возможно, вам не нужен дополнительный класс и для приложений достаточно, чтобы определить smap на верхнем уровне, и просто использовать, что вместо fmap,

smap :: (Functor f, Show a, Show b) => (a -> b) -> f a -> f b 
smap = fmap 
+0

Вероятно, 'ShowFunctor' не должен быть подклассом' Functor', поскольку он добавляет предварительное условие. Каждый «Functor» является «ShowFunctor», но не обязательно наоборот. –

+0

Я догадался, но это хорошо знать наверняка ... thx – frosch03

+0

Если смысл дальнейшего ограничения существующего класса, я думаю, что сделать его подкласс правильным.Если я полностью не понял и OP хочет, чтобы экземпляры 'ShowFunctor' могли только обернуть типы, принадлежащие' Show' ('data ShowList a, где ShowList :: Show a => [a] -> ShowList a; экземпляр ShowFunctor ShowList, где smap f (ShowList xs) = ShowList (fmap f xs) '), но это не может быть реализовано классом (по крайней мере, не в H2010). –

2

Вы не можете сделать это, не нарушая вещи (В данный момент).

У вас есть несколько вариантов

  1. определить свой собственный ограниченный Functor класс
  2. не переживайте об определении класса и просто определить функцию, которая делает то, что вы хотите
  3. использовать RMonad package
  4. чит

Фактически, теперь мы знаем, как разрешать экземпляры объявления d ограничений, поэтому, возможно, в один прекрасный день это не будет так плохо, см. Subcategories in Haskell для статьи, касающейся почти этой проблемы. Синтаксис в этой статье немного отличается от того, что в настоящее время работает в GHC, но в основном мы хотели бы пересмотреть Functor класс выглядеть

class Functor f where 
    type SubCat f :: * -> Constraint -- associated constraint 
    type SubCat f =() -- default definition 
    fmap :: (SubCat f a, SubCat f b) => (a -> b) -> f a -> f b 
Смежные вопросы