我不明白为什么我不能分解一个(比如说IO)单子。比如IO a -> a我的问题起源于使用happstack并希望从(optional $ lookText "domain")返回的ServerPart (Maybe Text)中获取Text。然后我想起阅读到IO monad不能被转义。我读过关于unsafePerformIO和它为什么不好的原因,但这些原因似乎都没有回答我的问题。
IO a -> a
(optional $ lookText "domain")
ServerPart (Maybe Text)
Text
IO
unsafePerformIO
9lowa7mx1#
Monad
是的。这对于许多Monad非常容易,例如Maybe,Either a,State s,Identity等等。最常见的Monad被转义的函数之一是Monad:(->) r。如果不能将函数转换为值,那么Haskell就没有什么用处了。
Maybe
Either a
State s
Identity
(->) r
很不幸是的对于初学者来说,如果他们没有google一下,看到他们可以使用unsafePerformIO从技术上逃离IO,这会更好,正如你可能已经猜到的那样 * 不安全 。它不是用于普通代码,而是当你真正需要它时进入运行时系统的后门。首先,它用于实现一些较低级别的库,如Vector,但也用于与外部共享库(DLL)接口。 如果你不写这种代码,不要使用unsafePerformIO*。否则,您最终得到的代码将变得难以推理和维护,因为它绕过了类型系统。
Vector
它从Monad到Monad不等,但大多数monad transformers都有run-,eval-或exec-方法:
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
MaybeMonad有几种方法可以摆脱它:
> :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来了解它。然而,快速搜索使我在他们的网站上找到了这个例子,它看起来非常适用于您的情况。
deikduxw2#
让我用另一个问题来回答你的问题:为什么你认为你能从单子里得到东西
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从单子中提取出来,并应用到你的函数中。如上所述,没有理由相信你能做到这一点。相反,你做相反的事情--你把你的函数带到类型中!
a
map f :: [a] -> [b]
2条答案
按热度按时间9lowa7mx1#
Monad
s可以转义吗?是的。这对于许多
Monad
非常容易,例如Maybe
,Either a
,State s
,Identity
等等。最常见的Monad
被转义的函数之一是Monad
:(->) r
。如果不能将函数转换为值,那么Haskell就没有什么用处了。IO
可以转义吗?很不幸是的对于初学者来说,如果他们没有google一下,看到他们可以使用
unsafePerformIO
从技术上逃离IO
,这会更好,正如你可能已经猜到的那样 * 不安全 。它不是用于普通代码,而是当你真正需要它时进入运行时系统的后门。首先,它用于实现一些较低级别的库,如Vector
,但也用于与外部共享库(DLL)接口。 如果你不写这种代码,不要使用unsafePerformIO
*。否则,您最终得到的代码将变得难以推理和维护,因为它绕过了类型系统。如何逃离其他
Monad
s?它从
Monad
到Monad
不等,但大多数monad transformers都有run-
,eval-
或exec-
方法:Maybe
Monad
有几种方法可以摆脱它:正如你所看到的,并不是所有的都可以安全使用。
这和Happstack有什么关系?
我不知道,我还没有足够的使用Happstack来了解它。然而,快速搜索使我在他们的网站上找到了这个例子,它看起来非常适用于您的情况。
deikduxw2#
让我用另一个问题来回答你的问题:为什么你认为你能从单子里得到东西
更直接地说,
Monad
使您能够 * 创建 * 和 * 合并 * 类型。这种形式存在许多类型,它们可能根本不允许您实际提取任何内容。一个更有意义、更直接的例子是list monad。
列表显然可以包含一些东西,但它们也可能失败。没有功能
它在传递
[]
时不会抛出错误。通常,您想要从monad中“得到一些东西”的原因是您有一个操作,
和一元值,如
你想把这个
a
从单子中提取出来,并应用到你的函数中。如上所述,没有理由相信你能做到这一点。相反,你做相反的事情--你把你的函数带到类型中!