简体   繁体   中英

Is there a way to derive Num class functions in own data type in Haskell?

Let's say I have a type declaration:

 data MyType = N Double | C Char | Placeholder

I want to be able to treat MyType as a Double whenever it's possible, with all the Num, Real, Fractional functions resulting in N (normal result) for arguments wrapped in the N constructor, and Placeholder for other arguments

> (N 5.0) + (N 6.0)
N 11.0
> (N 5.0) + (C 'a')
Placeholder

Is there a way to do this other than simply defining this class as an instance of those classes in a manner similar to:

instance Num MyType where
  (+) (N d1) (N d2) = N (d1+d2)
  (+) _ _ = Placeholder
  ...

(which seems counter-productive)?

There is no generic deriving available in standard Haskell : currently, deriving is only available as defined by the compiler for specific Prelude typeclasses: Read , Show , Eq , Ord , Enum , and Bounded .

The Glasgow Haskell Compiler (GHC) apparently has extensions that support generic deriving . However, I don't know if it would actually save you any work to try and use them: how many typeclasses do you need to derive a Num instance from? And, are you sure that you can define an automatic scheme for deriving Num that will always do what you want?

As noted in the comments, you need to describe what your Num instance will do in any case. And describing and debugging a general scheme is certain to be more work than describing a particular one.

No, you can't do this automatically, but I think what leftaroundabout could have been getting at is that you can use Applicative operations to help you.

data MyType n = N n | C Char | Placeholder deriving (Show, Eq, Functor)

instance Applicative MyType where
  pure = N
  (<*>) = ap

instance Monad MyType where
  N n >>= f = f n
  C c >>= _ = C c
  Placeholder >>= _ = Placeholder

Now you can write

instance Num n => Num (MyType n) where
  x + y = (+) <$> x <*> y
  abs = fmap abs
  ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM