haskell - How can I reuse a class instance for a newtype? -


i have defined type called natural positive integer includes 0:

newtype natural = natural integer     deriving (eq, ord) instance show natural   show (natural i) = show  tonatural :: (integral i) => -> natural tonatural x | x < 0     = error "natural cannot negative"             | otherwise = natural $ tointeger x  fromnatural :: natural -> integer fromnatural (natural i) =  instance num natural     frominteger = tonatural     x + y       = tonatural (fromnatural x + fromnatural y)     x - y       = let r = fromnatural x - fromnatural y in                       if r < 0 error "subtraction yielded negative value"                                else tonatural r     x * y       = tonatural (fromnatural x * fromnatural y)     abs x       = x     signum x    = tonatural $ signum $ fromnatural x  instance enum natural   toenum = tonatural . tointeger   fromenum = frominteger . fromnatural 

in code common newtypes take natural parameter. , since want these types instances of num , enum, find myself reimplementing same classes on , over:

newtype nodeid     = nodeid natural     deriving (show, eq, ord)  instance num nodeid     frominteger = nodeid . tonatural     (nodeid x) + (nodeid y) = nodeid (x + y)     (nodeid x) - (nodeid y) = nodeid (x - y)     (nodeid x) * (nodeid y) = nodeid (x * y)     abs (nodeid x) = nodeid (abs x)     signum (nodeid x) = nodeid (signum x)  instance enum nodeid   toenum = nodeid . toenum   fromenum (nodeid x) = fromenum x  ...  newtype instructionid = instructionid natural   deriving (show, eq)  instance num instructionid     frominteger = instructionid . tonatural     (instructionid x) + (instructionid y) = instructionid (x + y)     (instructionid x) - (instructionid y) = instructionid (x - y)     (instructionid x) * (instructionid y) = instructionid (x * y)     abs (instructionid x) = instructionid (abs x)     signum (instructionid x) = instructionid (signum x)  instance enum instructionid   toenum = instructionid . toenum   fromenum (instructionid x) = fromenum x  ...  newtype patternid = patternid natural   deriving (show, eq)  instance num patternid     frominteger = patternid . tonatural     (patternid x) + (patternid y) = patternid (x + y)     (patternid x) - (patternid y) = patternid (x - y)     (patternid x) * (patternid y) = patternid (x * y)     abs (patternid x) = patternid (abs x)     signum (patternid x) = patternid (signum x)  instance enum patternid   toenum = patternid . toenum   fromenum (patternid x) = fromenum x 

as see these implementations identical, made me wonder whether implement class a implement num , enum classes, , each newtype need implement simple function (maybe not function @ all) of a. i'm not sure how or whether it's possible @ all.

any ideas?

there's extension called generalizednewtypederiving can use same end. lets "carry over" definitions underlying type newtype.

here's small, contrived code example:

{-# language generalizednewtypederiving #-}  newtype foo = foo integer deriving (show, eq, num)\ 

it's bit confusing though: standard derived classes show , eq still derived normal way. foo's show instance different integer's. however, other classes carried through directly, foo's num instances same integer's.

you have little careful because does not play well haskell extensions. however, simple num case, it's option. believe upcoming versions of ghc fixing of common problems generalizednewtypederiving, should become safer extension in near future.


Comments

Popular posts from this blog

android - Get AccessToken using signpost OAuth without opening a browser (Two legged Oauth) -

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: mockito -

google shop client API returns 400 bad request error while adding an item -