Эксклюзивный экземпляр класса Haskell

Есть ли способ "поднять" экземпляр класса в 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 и других классов, когда я пытался изучить существующие имена, и компилятор не разрешил мне использовать deriving(Show).

Ответы

Ответ 1

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

{-# 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

Ответ 2

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

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

{-# GeneralizedNewtypeDeriving #-}

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

data SomeType a = SomeCons a deriving (Num)

Ответ 3

GeneralizedNewtypeDeriving