为什么不能单子分解?(Why can't a monad be decomposed?)

2019-10-20 04:47发布

我不明白为什么我不能一个分解(假设IO)单子。 像IO a -> a

我的问题使用happstack和希望得到的起源时, TextServerPart (Maybe Text)这是由返回(optional $ lookText "domain") 然后我想起读取IO单子无法逃脱。

我读过有关unsafePerformIO ,为什么它是坏的原因,但没有这些理由似乎回答我的问题。

Answer 1:

可以Monad s内从逃脱?

是。 这是很容易与许多Monad S,如MaybeEither aStateIdentity等。 其中最常见的Monad是从逃脱s是功能Monad(->) r 。 如果它是不可能把一个函数变成一个值,然后哈斯克尔不会有太多为它去。

可以IO从逃脱?

不幸的是,是的。 这将是对于初学者来说好了很多,如果他们没有谷歌四周,看看他们可以从技术上逃避IO使用unsafePerformIO ,正如你可能已经猜到了是不是安全 。 这并不意味着在正常代码中使用,相反却是一个后门程序到运行时系统,当你真的需要它。 主要地,它是用于实现像一些较低级别的库Vector ,而且还用于与外部共享库(DLL)的接口连接。 如果你不写那种代码,请不要使用unsafePerformIO 。 否则,你将最终的代码变得难于推理和维护,因为它绕过类型系统。

我们如何从其他逃避Monad S'

它从不同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

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足够的了解它。 然而,快速搜索使我这个在其网站上,这看起来很适用于您的情况的例子。



Answer 2:

让我来回答你的问题与另一个问题:为什么你认为你能得到的东西出一个单子?

data Dud a = Dud

instance Functor Dud where
  fmap _ _ = Dud

instance Monad Dud where
  return _  = Dud
  Dud >>= _ = Dud

更直接地说, Monad给你创造组合类型的能力。 这种形式可能不会让你在所有的实际提取任何的许多类型的存在。

一个更有意义的,直接的例子是列表单子。

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

bindList :: [a] -> (a -> [b]) -> [b]
bindList as f = concat (map f as)

显然列出可能包含的东西,但他们也可能无法。 有没有功能

[a] -> a

其中通过时,不会引发错误[]


通常情况下,你为什么要一个单子“得到的东西”的原因是,你有一个像操作

f :: a -> b

和一个monadic值等

m :: [a]

你想拉那a出来的单子,并把它应用到你的函数。 如上所述,我们没有理由相信你能做到这一点。

相反,你却反其道而行之,你把你的函数入式!

map f :: [a] -> [b]


文章来源: Why can't a monad be decomposed?