为什么一元不能分解?



我不明白为什么我不能分解一个(我们说IO)单子。如IO a -> a ?

我的问题起源于使用happstack并希望从(optional $ lookText "domain")返回的ServerPart (Maybe Text)中获得Text。然后我想起读到IO单子不能逃脱。

我读过unsafePerformIO和它不好的原因,但这些原因似乎都不能回答我的问题。

Monads可以被转义吗?

是的。对于许多Monad,如MaybeEither aStateIdentity等,这非常容易。转义最常见的Monad之一是函数Monad: (->) r。如果不能将函数转换为值,那么Haskell就不会有太多的优势了。

IO可以转义吗?

不幸的是,是的。对于初学者来说,如果他们没有到处搜索并看到他们可以使用unsafePerformIO从技术上逃离IO,那将会好得多,正如您可能已经猜到的那样,不安全。它是而不是在正常代码中使用,而是在您真正需要它时进入运行时系统的后门。它主要用于实现一些较低级别的库,如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,所以不知道它。然而,快速搜索使我在他们的网站上找到了这个例子,看起来很适合你的情况。

让我用另一个问题来回答你的问题:为什么你认为你可以从单子中得到东西?

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

和像

这样的一元值
m :: [a]

,您想将该a从单子中取出并将其应用于您的函数。如上所述,没有理由相信你能做到。

相反,您将做相反的事情—将函数引入到类型中!

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

相关内容

  • 没有找到相关文章

最新更新