2013-12-09 14 views
8

Ho un tipo che agisce in sostanza come un tag su un altro tipo di dati:"Ereditare" istanza di tipo avvolto

import Data.Word 
data RijndaelField = RF Word8 

voglio RijndaelField a "ereditare" l'istanza Word8 del Bits nel modo più semplice possibile:

import Data.Bits 
instance Bits RijndaelField where 
    RF a .&. RF b  = RF $ a .&. b 
    RF a .|. RF b  = RF $ a .|. b 
    RF a `xor` RF b = RF $ a `xor` b 
    complement (RF a) = RF $ complement a 
    shift (RF a) n = RF $ shift a n 
    rotate (RF a) n = RF $ rotate a n 
    bitSize (RF a) = bitSize a 
    isSigned (RF a) = isSigned a 
    testBit (RF a) n = testBit a n 
    bit n    = RF $ bit n 
    popCount (RF a) = popCount a 

esiste un modo più breve per esprimere che relazione tra RijndaelField e Word8?

risposta

12

Se non avete bisogno di ADT o tipi di record, si potrebbe usare un newtype invece con GeneralizedNewtypeDeriving:

{-# LANGUAGE GeneralizedNewtypeDeriving #-} 

import Data.Bits 
import Data.Word 

newtype RF = RF { unRF :: Word8 } deriving (Eq, Bits) 

Se si voleva davvero, è possibile includere un sacco di altre classi

newtype RF = RF { unRF :: Word8 } 
    deriving (Eq, Bits, Num, Integral, Real, Enum, Ord, Show) 

Il che consente di utilizzare come

> 1 :: RF 
RF {unRF = 1} 
> [1..5] :: [RF] 
[RF {unRF = 1},RF {unRF = 2},RF {unRF = 3},RF {unRF = 4},RF {unRF = 5}] 
> let x = RF 1 
> x + 2 
RF {unRF = 3} 

Che penso sia abbastanza comodo

+0

Questo è esattamente quello che stavo cercando, grazie. (C'è un'estensione per ogni cosa!) – Snowball

+0

@Snowball Quasi =) Questo è particolarmente utile quando si avvolge una pila di trasformatori monad, si può avere il compilatore derivando cose come 'Monad',' Functor', 'MonadTrans',' MonadState MyState', 'Applicative', e altro ancora. È molto utile per generare un sacco di codice boilerplate. – bheklilr

Problemi correlati