如何使"liftM2 (+) (T 1) (T 2)"为"newtype T = T Int"生产"T 3"



我有一个类型T定义如下,我想在其中封装一个整数。

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

现在,如果我想包装一个操作,包装器中的值并返回类似于liftM*所做的结果,就像上面的代码所示,但它不起作用。我希望有一组函数的作用类似下面的myLiftT2,但应用范围更广。

myLiftT2 :: (Int -> Int -> Int) -> T -> T -> T
myLiftT2 f (T a) (T b) = T $ f a b
myLiftT2 (+) (T 1) (T 2)     -- `T 3'

我知道我可以把它定义为Monad或Applicative,实际上效果很好:

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

考虑到不必要性,我只是不想在类型后面添加多态性参数a,因为T应该只包装整数。

我很好奇人们通常是如何处理或规避这种不便的。谢谢

这个怎么样:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype T  = T Int deriving (Show, Eq, Num)

ghci:演示

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

如果你只想总结一下,我觉得没有必要把它作为Monad的一个例子。

最新更新