为什么monad不能被分解?

Ant*_*ton 1 io monads haskell happstack

我不明白为什么我不能分解(让我们说IO)monad.喜欢IO a -> a

我的问题使用happstack和想要得到的时候起源Text的出ServerPart (Maybe Text)这是由返回(optional $ lookText "domain").然后我记得读到IOmonad无法逃脱.

我已经读过unsafePerformIO它以及它为什么不好的原因,但这些原因似乎都没有回答我的问题.

bhe*_*ilr 10

可以Monad逃脱吗?

是.这是很容易与许多MonadS,如Maybe,Either a,State,Identity,等等.Monad逃脱的最常见的一个是功能Monad:(->) r.如果无法将函数转换为值,那么Haskell就没有太大的意义了.

可以IO逃脱吗?

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

我们如何逃避其他Monad

从变化MonadMonad,但大部分单子变压器具有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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

如您所见,并非所有这些都可以安全使用.

这与Happstack有什么关系?

我不知道,我还没有充分利用Happstack来了解它.然而,快速搜索引导我在他们的网站上看到这个例子,这看起来非常适合你的情况.


J. *_*son 5

让我用另一个问题回答你的问题:为什么你认为你可以从monad中获取东西?

data Dud a = Dud

instance Functor Dud where
  fmap _ _ = Dud

instance Monad Dud where
  return _  = Dud
  Dud >>= _ = Dud
Run Code Online (Sandbox Code Playgroud)

更直接地,Monad您可以创建组合类型.这种形式存在许多类型,可能根本不允许您实际提取任何内容.

列表monad是一个更有意义的直接示例.

returnList :: a -> [a]
returnList a = [a]

bindList :: [a] -> (a -> [b]) -> [b]
bindList as f = concat (map f as)
Run Code Online (Sandbox Code Playgroud)

列表显然可能包含内容,但它们也可能无法实现.没有功能

[a] -> a
Run Code Online (Sandbox Code Playgroud)

传递时不会抛出错误[].


通常,你想要从monad中"取出"的原因是你有一个类似的操作

f :: a -> b
Run Code Online (Sandbox Code Playgroud)

和monadic值一样

m :: [a]
Run Code Online (Sandbox Code Playgroud)

并且你想把它a从monad中拉出来并应用到你的函数中.如上所述,没有理由相信你可以做到这一点.

相反,你做相反的事情 - 你将你的功能带入类型!

map f :: [a] -> [b]
Run Code Online (Sandbox Code Playgroud)