我不明白为什么我不能分解(比如说 IO)单子。喜欢IO a -> a
?
我的问题起源于使用 happstack 并希望从中得到Text
. 然后我记得读到monad 是无法逃脱的。 ServerPart (Maybe Text)
(optional $ lookText "domain")
IO
我已经阅读了unsafePerformIO
它不好的原因及其原因,但这些原因似乎都没有回答我的问题。
Monad
逃脱吗?是的。这对于许多 s 来说非常容易Monad
,例如Maybe
, Either a
, State
,Identity
等等。最常见Monad
的逃逸 s 之一是函数Monad
: (->) r
。如果不可能将一个函数变成一个值,那么 Haskell 就没有什么用处了。
IO
逃脱吗?不幸的是,是的。对于初学者来说,如果他们没有在谷歌周围搜索并看到他们可以从技术上逃脱IO
using unsafePerformIO
,那会好得多,正如您可能已经猜到的那样,这是不安全的。它并不打算在普通代码中使用,而是在您真正需要时进入运行时系统的后门。首先,它用于实现一些较低级别的库,例如Vector
.,但也用于与外部共享库 (DLL) 的接口。 如果您不编写那种代码,请不要使用unsafePerformIO
. 否则,您最终会得到难以推理和维护的代码,因为它绕过了类型系统。
Monad
s中逃脱?它从Monad
到变化Monad
,但大多数 monad 转换器具有run-
或eval-
方法exec-
:
> :m Control.Monad.State
> runState (modify (*10) >> get >>= return . show) 1
("10", 10)
> :type runState (modify (*10) >> get >>= return . show) 1
runState (modify (*10) >> get >>= return . show) 1 :: (String, Int)
> evalState (modify (*10) >> get >>= return . show) 1
"10"
> execState (modify (*10) >> get >>= return . show) 1
10
有Maybe
Monad
几种方法可以摆脱它:
> :m Data.Maybe
> maybe "nada" show (Just 2)
"2"
> maybe "nada" show Nothing
"nada"
> fromMaybe 1 (Just 10)
10
> fromMaybe 1 Nothing
1
> fromJust (Just 1)
1
> fromJust Nothing
*** Exception: Maybe.fromJust: Nothing
如您所见,并非所有这些都可以安全使用。
我不知道,我对 Happstack 的了解还不够。然而,快速搜索让我在他们的网站上找到了这个例子,这看起来很适合你的情况。
让我用另一个问题来回答你的问题:你为什么认为你可以从 monad 中得到东西?
data Dud a = Dud
instance Functor Dud where
fmap _ _ = Dud
instance Monad Dud where
return _ = Dud
Dud >>= _ = Dud
更直接地,Monad
使您能够创建和组合类型。这种形式存在许多类型,可能根本不允许您实际提取任何内容。
一个更有意义、更直接的例子是 list monad。
returnList :: a -> [a]
returnList a = [a]
bindList :: [a] -> (a -> [b]) -> [b]
bindList as f = concat (map f as)
列表显然可能包含东西,但它们也可能不包含。没有功能
[a] -> a
通过时不会引发错误[]
。
通常,您想从 monad 中“获取某些东西”的原因是您有类似的操作
f :: a -> b
和一个像
m :: [a]
并且您想将其a
从 monad 中提取出来并将其应用于您的函数。如上所述,没有理由相信您可以做到这一点。
相反,你会做相反的事情——你把你的函数带入类型中!
map f :: [a] -> [b]