2014-02-28 82 views
1

我有一个类型为T的定义如下,我想包装一个整数在里面。如何使“liftM2(+)(T 1)(T 2)”为“新类型T = T Int”生成“T 3”

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' 

我知道我可以把它定义为一个单子或者应用型,实际上是工作的好:

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 

考虑unnecessarity,我只是不想后添加一个多态参数a因为T应该只包含整数。

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

+0

我通常会添加类型参数。有时它开启了我没有想过的可能性。但这实际上取决于'T'的目的是什么。 – luqui

回答

6

如何:

{-# LANGUAGE GeneralizedNewtypeDeriving #-} 

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

演示了ghci:

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

我不觉得有必要为使其作为Monad一个实例,如果你只是想总结他们了。

相关问题