Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Inheriting" instance of wrapped type

I have a type that basically acts as a tag on another data type:

import Data.Word
data RijndaelField = RF Word8

I want RijndaelField to "inherit" the Word8 instance of Bits in the simplest way possible:

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

Is there a shorter way to express that relation between RijndaelField and Word8?

like image 866
Snowball Avatar asked Dec 09 '13 22:12

Snowball


1 Answers

If you don't need ADTs or record types, you could use a newtype instead with GeneralizedNewtypeDeriving:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

import Data.Bits
import Data.Word

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

If you really wanted to, you can include a lot of other classes

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

Which would let you use it as

> 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}

Which I think it quite handy

like image 70
bheklilr Avatar answered Sep 19 '22 03:09

bheklilr