Question

I have a type T defined as below and I want to wrap an integer in it.

newtype T = T Int
-- liftM2 (+) (T 1) (T 2)    -- error: `T' is not an instance of Monad

Now if I want to wrap an operation the values in the wrappers and return a similar the result like what liftM* does, just as shown in above code, but it doesn't work. I expect a group of functions that act like myLiftT2 below but apply more generally.

myLiftT2 :: (Int -> Int -> Int) -> T -> T -> T
myLiftT2 f (T a) (T b) = T $ f a b

myLiftT2 (+) (T 1) (T 2)     -- `T 3'

I know I can define it as a Monad or an Applicative and actually that works good:

newtype T a = T a

instance Monad T where
  (T a) >>= f = f a
  return      = T

liftM2 (+) (T 1) (T 2)        -- produces `(T 3)' as expect

Considering the unnecessarity, I just don't want to add a polymorphism parameter a after the type because T should only wrap integers.

I am curious how people usually deal with, or circumvent, this inconvenience. Thanks.

Was it helpful?

Solution

How about this:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

newtype T  = T Int deriving (Show, Eq, Num)

Demo in ghci:

ghci> (T 1) + (T 2)
T 3

I don't feel there is a need for making it as an instance of Monad, if you just want to sum them up.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top