我不明白为什么我不能分解(比如IO)monad。喜欢IO a -> a
?
我的问题源于使用happstack并希望从Text
返回的ServerPart (Maybe Text)
(optional $ lookText "domain")
。
然后我记得读到IO
monad无法逃脱。
我读过关于unsafePerformIO
及其原因的原因,但这些原因似乎都没有回答我的问题。
答案 0 :(得分:10)
Monad
可以从中逃脱吗?是。对于许多Monad
来说,这非常简单,例如Maybe
,Either a
,State
,Identity
等。转义最常见的Monad
之一是函数Monad
:(->) r
。如果无法将函数转换为值,那么Haskell就没有太大的意义了。
IO
转出吗?不幸的是,是的。对于初学者来说,如果他们没有谷歌并且看到他们可以从IO
使用unsafePerformIO
从技术上逃脱,那将会好得多,正如您可能已经猜到的那样不安全。 不意味着在普通代码中使用,但它是运行时系统的后门,当你真正需要它时。它主要用于实现一些较低级别的库,如Vector
,但也用于连接外部共享库(DLL)。 如果您没有编写此类代码,请不要使用unsafePerformIO
。否则,您将最终得到难以推理和维护的代码,因为它绕过了类型系统。
Monad
?从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来了解它。但是,通过快速搜索,我可以在他们的网站上找到this示例,这看起来非常适合您的情况。
答案 1 :(得分:5)
让我用另一个问题回答你的问题:为什么你认为你可以从单子中得到东西?
data Dud a = Dud
instance Functor Dud where
fmap _ _ = Dud
instance Monad Dud where
return _ = Dud
Dud >>= _ = Dud
更直接地,Monad
使您能够创建和合并类型。这种形式存在许多类型,可能根本不允许您实际提取任何内容。
更有意义的直接示例是列表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
和像
这样的monadic值m :: [a]
并且您想将a
拉出monad并将其应用到您的函数中。如上所述,没有理由相信你能做到这一点。
相反,你做的相反 - 你把你的功能带入了类型!
map f :: [a] -> [b]