为什么不能分解monad?

时间:2014-05-28 02:17:03

标签: haskell io monads happstack

我不明白为什么我不能分解(比如IO)monad。喜欢IO a -> a

我的问题源于使用happstack并希望从Text返回的ServerPart (Maybe Text) (optional $ lookText "domain")。 然后我记得读到IO monad无法逃脱。

我读过关于unsafePerformIO及其原因的原因,但这些原因似乎都没有回答我的问题。

2 个答案:

答案 0 :(得分:10)

Monad可以从中逃脱吗?

是。对于许多Monad来说,这非常简单,例如MaybeEither aStateIdentity等。转义最常见的Monad之一是函数Monad(->) r。如果无法将函数转换为值,那么Haskell就没有太大的意义了。

可以IO转出吗?

不幸的是,是的。对于初学者来说,如果他们没有谷歌并且看到他们可以从IO使用unsafePerformIO从技术上逃脱,那将会好得多,正如您可能已经猜到的那样不安全意味着在普通代码中使用,但它是运行时系统的后门,当你真正需要它时。它主要用于实现一些较低级别的库,如Vector,但也用于连接外部共享库(DLL)。 如果您没有编写此类代码,请不要使用unsafePerformIO 。否则,您将最终得到难以推理和维护的代码,因为它绕过了类型系统。

我们如何逃离其他Monad

MonadMonad不等,但大多数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有什么关系?

我不知道,我还没有充分利用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]