2015-11-08 4 views
3

Я пытаюсь сделать typeclass для подписанных числовых типов. Вот мой код:Экземпляр Haskell с ограничением

{-# LANGUAGE TypeFamilies, FlexibleContexts, UndecidableInstances #-} 

data Sign = Negative | Zero | Positive 
    deriving (Eq, Ord, Read, Show) 

class Signed a where 
    sign :: a -> Sign 

instance Signed Integer where 
    sign = undefined 

компилируется, но я хотел бы, чтобы адаптировать этот код, чтобы работать на любом Integral a.

instance (Integral a) => Signed a where 
    sign = undefined 

В этот момент он не компилируется.

Я проверил Haskell type family instance with type constraints, но это похоже на проблему, отличную от моей. Я не думаю, что в моем коде есть синтаксическая ошибка .

+0

Вам нужно включить 'OverlappingInstances', я думаю. С другой стороны, я думаю, что положить знак в класс может быть ошибкой в ​​этом случае - просто определите функцию верхнего уровня 'sign :: Integral a => a -> Sign'. –

+0

Просто попробовал. Кажется, не меняется. 'instance Signed Integer' все еще компилируется, но' instance (Integral a) => ... 'все еще терпит неудачу. –

+1

ОК, я поместил ваш код в файл, и GHC сказал мне, что мне нужно включить 'FlexibleInstances' тоже. С этим он компилируется сразу. (Сообщения об ошибках GHC обычно весьма специфичны, о каких расширениях вам нужно включить.) –

ответ

2

Попытка компиляции кода выдает следующее сообщение об ошибке:

sign.hs:9:26: 
    Illegal instance declaration for ‘Signed 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 ‘Signed a’ 
Failed, modules loaded: none. 

Как компилятор указывает, что вам нужно включить FlexibleInstances, а также UndecidableInstances. Сообщения об ошибках GHC обычно весьма специфичны, особенно если вы забыли включить расширение языка. Следующие компилирует срочно:

{-# LANGUAGE UndecidableInstances, FlexibleInstances #-} 

data Sign = Negative | Zero | Positive 
    deriving (Eq, Ord, Read, Show) 

class Signed a where 
    sign :: a -> Sign 

instance (Integral a) => Signed a where 
    sign = undefined 

Однако, я думаю, что Signed класс может быть ошибка в этом примере. Определение функции (не перегруженного) верхнего уровня намного проще, не требует UndecidableInstances (потребность в которой часто является дизайнерским запахом) и более выразительна для , что означает вашего кода: «вещи, которые вы можете получить знак «являются точно действительными числами.

sign :: Real a => a -> Sign 
sign x 
    | x == 0 = Zero 
    | x < 0 = Negative 
    | otherwise = Positive 
+0

Благодарим вас за предоставленный такой полезный ответ. Рад, что я могу избавиться от стилей и прагм. –

+0

Рад помочь! :) –