1

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

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

我已经阅读了unsafePerformIO它不好的原因及其原因,但这些原因似乎都没有回答我的问题。

4

2 回答 2

10

s可以Monad逃脱吗?

是的。这对于许多 s 来说非常容易Monad,例如Maybe, Either a, State,Identity等等。最常见Monad的逃逸 s 之一是函数Monad: (->) r。如果不可能将一个函数变成一个值,那么 Haskell 就没有什么用处了。

IO逃脱吗?

不幸的是,是的。对于初学者来说,如果他们没有在谷歌周围搜索并看到他们可以从技术上逃脱IOusing unsafePerformIO,那会好得多,正如您可能已经猜到的那样,这是不安全的。它并不打算在普通代码中使用,而是在您真正需要时进入运行时系统的后门。首先,它用于实现一些较低级别的库,例如Vector.,但也用于与外部共享库 (DLL) 的接口。 如果您不编写那种代码,请不要使用unsafePerformIO. 否则,您最终会得到难以推理和维护的代码,因为它绕过了类型系统。

我们如何从其他Monads中逃脱?

它从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 有什么关系?

我不知道,我对 Happstack 的了解还不够。然而,快速搜索让我在他们的网站上找到了这个例子,这看起来很适合你的情况。

于 2014-05-28T02:55:34.087 回答
5

让我用另一个问题来回答你的问题:你为什么认为你可以从 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]
于 2014-05-28T03:01:22.207 回答