Незаконное объявление экземпляра в Haskell - PullRequest
0 голосов
/ 29 ноября 2018

Я попробовал следующий код

class Group a where
  (.+.) :: a -> a -> a
  (.-.) :: a -> a -> a
  zero :: a
  opposite :: a -> a

  x .-. y = x .+. opposite y
  opposite x = zero .-. x
  {-# MINIMAL (.+.), zero, (opposite | (.-.)) #-}

instance Fractional a => Group a where
  x .+. y = x + y
  zero = 0 :: a
  opposite = negate :: a -> a

Но при загрузке в GHCi я получаю следующую ошибку:

group1.hs:11:26: error:
    • Illegal instance declaration for ‘Group 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 ‘Group a’
   |
11 | instance Fractional a => Group a where
   |    

Что я делаю не так?

Ответы [ 2 ]

0 голосов
/ 29 ноября 2018

Мне удалось скомпилировать ваш пример:

{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}

class Group a where
  (.+.) :: a -> a -> a
  (.-.) :: a -> a -> a
  zero :: a
  opposite :: a -> a

  x .-. y = x .+. opposite y
  opposite x = zero .-. x
  {-# MINIMAL (.+.), zero, (opposite | (.-.)) #-}

-- data Fractional a = Fractional a a

instance (Fractional a, Num a) => Group a where
  x .+. y = x + y
  zero = 0
  opposite = negate
  • FlexibleInstances разрешить экземпляр неизвестного типа с ограничениями.По сути, нам нужно instance X a
  • UndecidableInstances, потому что мы объявляем, что любой a принадлежит классу Group, и это может (неизбежно?) Привести к a, принадлежащему Group через несколько различныхinstance декларации.
0 голосов
/ 29 ноября 2018

Ах!Я наконец понял, что не так.В Haskell класс может быть создан только для ADT.Таким образом, единственное разумное решение - объявить что-то следующим образом:

class Group a where
  (.+.) :: a -> a -> a
  (.-.) :: a -> a -> a
  zero :: a
  opposite :: a -> a

  x .-. y = x .+. opposite y
  opposite x = zero .-. x
  {-# MINIMAL (.+.), zero, (opposite | (.-.)) #-}

newtype GroupType a = GroupType a  

instance Fractional a => Group (GroupType a) where
  GroupType x .+. GroupType y = GroupType $ x + y
  zero = GroupType 0
  opposite (GroupType x) = GroupType $ negate x
...