Подъемный экземпляр класса в Хаскеле - PullRequest
13 голосов
/ 30 ноября 2009

Есть ли способ легко "поднять" экземпляр класса в Haskell?

Мне часто приходилось создавать, например, экземпляры Num для некоторых классов, которые просто "поднимают" структуру Num с помощью конструктора типов следующим образом:

data SomeType a = SomeCons a

instance (Num a)=>Num SomeCons a where
    (SomeCons x) + (SomeCons y) = SomeCons (x+y)
    negate (SomeCons x) = SomeCons (negate x)
    -- similarly for other functions.

Есть ли способ избежать этого шаблона и автоматически "поднять" эту структуру Num? Я обычно делаю это с Show и другими классами, когда я пытаюсь изучить existencials, и компилятор не позволяет мне использовать deriving(Show).

Ответы [ 3 ]

19 голосов
/ 30 ноября 2009

Обобщенное производное расширение нового типа - это то, что вы хотите здесь:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

module Main where

newtype SomeType a = SomeCons a deriving (Num, Show, Eq)

main = do
  let a = SomeCons 2
      b = SomeCons 3
  print $ a + b

Выход:

*Main> main
SomeCons 5
5 голосов
/ 30 ноября 2009

GHC реализует то, что вы хотите: Расширение до производного механизма . Эти модификации часто показываются для будущего расширения стандартного языка (как видно на haskell 'wiki )

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

{-# GeneralizedNewtypeDeriving #-}

и затем используйте производную в вашем объявлении newtype, как обычно

data SomeType a = SomeCons a deriving (Num)
1 голос
/ 30 ноября 2009

GeneralizedNewtypeDeriving

...