是否有带有签名的内置函数:: (Monad m) => m a -> a
?
Hoogle 说没有这样的功能。
你能解释一下为什么吗?
monad 只提供两个功能:
return :: Monad m => a -> m a
(>>=) :: Monad m => m a -> (a -> m b) -> m b
这两个都返回类型的东西m a
,所以没有办法以任何方式组合它们来获得类型的函数Monad m => m a -> a
。为此,您需要的不仅仅是这两个函数,因此您需要了解m
的不仅仅是它是一个 monad。
例如,Identity
monad 有runIdentity :: Identity a -> a
,并且几个 monad 有类似的功能,但是没有办法通用地提供它。事实上,无法从 monad 中“逃脱”对于像IO
.
可能有比这更好的答案,但是要了解为什么不能拥有类型的一种(Monad m) => m a -> a
方法是考虑 null monad:
data Null a = Null
instance Monad Null where
return a = Null
ma >>= f = Null
现在的(Monad m) => m a -> a
意思是Null a -> a
,从无到有。你不能那样做。
这不存在,因为Monad
它是一种组合模式,而不是一种分解模式。您总是可以将更多部分与它定义的接口放在一起。它并没有说要拆开任何东西。
问你为什么不能取出某些东西就像问为什么 Java 的Iterator
接口不包含一个方法来添加元素到它正在迭代的东西。这不是Iterator
界面的用途。
您关于具有某种提取功能的特定类型的论点以完全相同的方式遵循。的某些特定实现Iterator
可能具有add
功能。但是由于它不是Iterator
s 的用途,因此该方法在某些特定实例上的存在是无关紧要的。
并且存在fromJust
同样无关紧要。Monad
这不是要描述的行为的一部分。其他人给出了许多没有价值的类型示例extract
。但是这些类型仍然支持Monad
. 这个很重要。这意味着这Monad
是一个比您认为的更通用的界面。
假设有这样一个函数:
extract :: Monad m => m a -> a
现在你可以写一个这样的“函数”:
appendLine :: String -> String
appendLine str = str ++ extract getLine
除非extract
保证函数永远不会终止,否则这将违反引用透明性,因为appendLine "foo"
(a) 的结果将取决于 以外的其他内容"foo"
,(b) 在不同的上下文中评估时评估为不同的值。
或者用更简单的话来说,如果有一个真正有用的extract
操作,Haskell 就不会是纯粹的功能性操作。
是否有带有签名的内置函数
:: (Monad m) => m a -> a
?
如果 Hoogle 说没有……那么可能没有,假设您对“内置”的定义是“在基础库中”。
Hoogle 说没有这样的功能。你能解释一下为什么吗?
这很容易,因为 Hoogle 在基础库中没有找到任何与该类型签名匹配的函数!
更严重的是,我想你是在要求一元解释。问题是安全和意义。(另见我之前的想法magicMonadUnwrap :: Monad m => m a -> a
)
假设我告诉你我有一个类型为 的值[Int]
。由于我们知道这[]
是一个 monad,这类似于告诉你我有一个类型为 的值Monad m => m Int
。所以让我们假设你想Int
摆脱它[Int]
。嗯,Int
你想要哪个?第一个?最后一个?如果我告诉你的值实际上是一个空列表怎么办?在那种情况下,甚至没有Int
给你!因此,对于列表,尝试像这样随意提取单个值是不安全的。即使它是安全的(非空列表),您也需要一个特定于列表的函数(例如,)head
来阐明您希望. 希望你能从这里直觉到f :: [Int] -> Int
Monad m => m a -> a
根本没有很好的定义。对于同一个 monad,它可能有多种含义,或者对于某些 monad 可能完全没有任何意义,有时,它只是不安全。
因为它可能没有意义(实际上,在许多情况下确实没有意义)。
例如,我可能会像这样定义 Parser Monad:
data Parser a = Parser (String ->[(a, String)])
现在绝对没有明智的默认方法来String
摆脱Parser String
. 实际上,仅使用 Monad 根本无法从中获取字符串。
在http://hackage.haskell.org/package/comonad-5.0.4/docs/Control-Comonad.html有一个有用的extract
功能和一些与此相关的其他功能
它只是为一些函子/单子定义的,它不一定给你完整的答案,而是给出一个答案。因此,comonad 的子类可能会为您提供选择可以控制的答案的中间阶段。可能与 Traversable 的可能子类有关。我不知道这些东西是否在任何地方都有定义。
为什么hoogle根本没有列出这个函数似乎是因为comonad包没有被索引,否则我认为Monad约束会被警告并且extract
会出现在那些带有Comonad
实例的Monads的结果中。也许这是因为 hoogle 解析器不完整,并且在某些代码行上失败。
我的替代答案:
monad >>= \a -> return $ your code uses a here
代码作为替代代码结构链接到 monad 中,只要您可以将 monad 转换为“IO ()”,以打印您完成的输出。这看起来不像提取,但数学与现实世界不同。好吧,从技术上讲,IO monad 有unsafePerformIO。
但是,正如名字本身所暗示的那样,这个功能是邪恶的,你应该只在你真的知道你在做什么的情况下使用它(如果你必须问你是否知道,那么你不知道)