如何使"liftM2(+)(T 1)(T 2)"工作以生成"newtype T = T Int"的"T 3"

Sho*_* Ya 1 monads haskell applicative

我有一个类型T定义如下,我想在其中包含一个整数.

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

现在,如果我想在包装器中包装一个操作值并返回类似于结果的结果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'
Run Code Online (Sandbox Code Playgroud)

我知道我可以将它定义为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
Run Code Online (Sandbox Code Playgroud)

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

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

Sib*_*ibi 6

这个怎么样:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

newtype T  = T Int deriving (Show, Eq, Num)
Run Code Online (Sandbox Code Playgroud)

演示ghci:

ghci> (T 1) + (T 2)
T 3
Run Code Online (Sandbox Code Playgroud)

Monad如果你只想总结它,我觉得不需要把它作为一个例子.