Haskell 将MaybeT与'join'连用`

Haskell 将MaybeT与'join'连用`,haskell,Haskell,查看MaybeT变压器: ghci> let x = MaybeT $ Just 1234 ghci> let y = runMaybeT x ghci> :t y y :: Num (Maybe a) => Maybe (Maybe a) 现在我想获得内部可能是一个,但是连接不起作用 ghci> join y <interactive>:53:1: No instance for (Num (Maybe a0)) arising from

查看
MaybeT
变压器:

ghci> let x = MaybeT $ Just 1234
ghci> let y = runMaybeT x
ghci> :t y
y :: Num (Maybe a) => Maybe (Maybe a)
现在我想获得内部
可能是一个
,但是
连接
不起作用

ghci> join y

<interactive>:53:1:
    No instance for (Num (Maybe a0)) arising from a use of `it'
    In a stmt of an interactive GHCi command: print it
ghci>join y
:53:1:
没有因使用“it”而产生的(Num(可能是a0))实例
在交互式GHCi命令的stmt中:打印它

如何获取内部
可能是一个
值?

可能的
类型是:

MaybeT :: Monad m => m (Maybe a) -> MaybeT m a
因此,
MaybeT$Just 1234
(您的问题中绑定到
x
的表达式)的类型是:

Haskell number文本被重载,并将根据上下文要求进行解释。在您的例子中,“包装”的monad
m
Maybe
,编译器试图将文本
1234
解释为
Maybe
,但没有
Num
实例。这解释了您遇到的类型错误

如果你真的想要一个
可能是一个
,你的代码应该是:

ghci> let x = MaybeT $ Just $ Just 1234
ghci> :t x
x :: Num a => MaybeT Maybe a
ghci> let y = runMaybeT x
ghci> :t y
y :: Num a => Maybe (Maybe a)
ghci> join y
Just 1234
但是,您更可能希望使用
MaybeT
转换器将成功/失败或结果/无结果上下文添加到现有(一元)计算中。使用
Identity
monad的最小示例:

ghci> let x = MaybeT $ Identity $ Just 1234
ghci> :t x
x :: Num a => MaybeT Identity a
ghci> let y = runMaybeT x
ghci> :t y
y :: Num a => Identity (Maybe a)
ghci> runIdentity y
Just 1234

您没有正确使用
MaybeT
构造函数。查看类型签名:

MaybeT    ::            m   (Maybe a) -> MaybeT m a
                        |   |       |
                      /-+-\ \---+---/
                      |   |     |
Just 1234 :: Num x => Maybe     x
因此:

m := Maybe
x := Maybe a
因此:

MaybeT $ Just 1234 :: Num (Maybe a) => MaybeT Maybe a
MaybeT $ return $ Just 1234 :: (Num a, Monad m) => MaybeT m a
所以这里
可能a
Num
的一个实例,这显然是错误的。选项类型不是数字。为什么会出现这个问题

考虑数值文本
1234
。数字文字是Haskell中的有界多态值。因此,它们的类型为
numx=>x
。换句话说,
1234
可以是任何类型,取决于上下文,只要该类型是
Num
的实例(例如
Int
Integer
Double

在代码中,多态类型
x
被实例化为
maybea
,这就是Haskell希望
maybea
成为
Num
实例的原因

我想你真正想做的是:

MaybeT             ::                     m (Maybe a) -> MaybeT m a

return $ Just 1234 :: (Num a, Monad m) => m (Maybe a)
因此:

MaybeT $ Just 1234 :: Num (Maybe a) => MaybeT Maybe a
MaybeT $ return $ Just 1234 :: (Num a, Monad m) => MaybeT m a
现在,您可以轻松提取内部
,可能是一个

runMaybeT $ MaybeT $ return $ Just 1234 :: (Num a, Monad m) => m (Maybe a)
(runMaybeT $ MaybeT $ return $ Just 1234) >>= \x -> do
    -- do something with x
    -- x :: Maybe a
由于内部
可能是一个
值被包装在一个monad中,所以您只需使用
>=
来提取
可能是一个

runMaybeT $ MaybeT $ return $ Just 1234 :: (Num a, Monad m) => m (Maybe a)
(runMaybeT $ MaybeT $ return $ Just 1234) >>= \x -> do
    -- do something with x
    -- x :: Maybe a
您也可以使用
do
符号编写此代码:

do
    x <- runMaybeT $ MaybeT $ return $ Just 1234
    -- do something with x
    -- x :: Maybe a
do

x ah,因此
maybetma
中的
a
应该是包装的
monad
?@KevinMeredith否,
maybetma
中的
a
不应该是包装的monad。它应该是包装的monad中的值的类型。明确地说,
maybetma
意味着一个
可能是一个包装在monad
m
中的值。这里包装的单子是
可能是a
,而不是
a
a
只是包装在
Maybe
中的值,该值依次包装在monad
m
中@阿迪姆沙是对的。听他说:)
Control.Monad加入