ДМИ*_*КОВ 39 monads haskell comonad
是否有带签名的内置功能:: (Monad m) => m a -> a?
Hoogle告诉我们没有这样的功能.
你能解释一下原因吗?
ham*_*mar 48
monad只提供两个功能:
return :: Monad m => a -> m a
(>>=) :: Monad m => m a -> (a -> m b) -> m b
Run Code Online (Sandbox Code Playgroud)
这两个都返回类型m a,所以没有办法以任何方式组合这些以获得类型的函数Monad m => m a -> a.要做到这一点,你需要的不仅仅是这两个函数,所以你需要了解更多,而m不是它是一个monad.
例如,Identitymonad具有runIdentity :: Identity a -> a,并且几个monad具有类似的功能,但是没有办法一般地提供它.事实上,无法从monad中"逃脱"对于monad来说是必不可少的IO.
Owe*_*wen 23
可能有一个比这个更好的答案,但是一种方法来了解为什么你不能有一个类型(Monad m) => m a -> a是考虑一个空monad:
data Null a = Null
instance Monad Null where
return a = Null
ma >>= f = Null
Run Code Online (Sandbox Code Playgroud)
现在(Monad m) => m a -> a意味着Null a -> a,即从无中生有的东西.你不能这样做.
Car*_*arl 14
这不存在,因为它Monad是一种组合模式,而不是一种分解模式.您可以随时将更多部分与其定义的界面放在一起.它没有说任何分开的事情.
问为什么你不能拿出一些东西就像问为什么Java的Iterator接口不包含一个方法来添加迭代的元素.它不是Iterator界面的用途.
关于具有一种提取函数的特定类型的论证遵循完全相同的方式.某些特定的实现Iterator可能具有一个add功能.但是因为它不是什么Iterator,所以在某个特定实例上存在该方法是无关紧要的.
而存在fromJust也同样无关紧要.这不是行为Monad旨在描述的一部分.其他人提供了许多类型的例子,其中没有价值extract可供使用.但那些类型仍然支持其预期的语义Monad.这个很重要.这意味着这Monad是一个比你给予赞誉的更通用的界面.
假设有这样一个功能:
extract :: Monad m => m a -> a
Run Code Online (Sandbox Code Playgroud)
现在你可以像这样编写一个"函数":
appendLine :: String -> String
appendLine str = str ++ extract getLine
Run Code Online (Sandbox Code Playgroud)
除非extract保证函数永远不会终止,否则这将违反引用透明性,因为appendLine "foo"(a)的结果将取决于"foo"(b)在不同上下文中求值时评估为不同值的其他内容.
或者用更简单的话来说,如果有一个实际有用的extract操作,Haskell将不是纯粹的功能.
是否有带签名的内置函数
:: (Monad m) => m a -> a?
如果Hoogle说没有......那么可能没有,假设您对"内置"的定义是"在基础库中".
Hoogle告诉我们没有这样的功能.你能解释一下原因吗?
这很简单,因为Hoogle在基础库中找不到与该类型签名匹配的任何功能!
更严重的是,我想你要求的是monadic解释.问题是安全和意义.(另见我以前的想法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)])
Run Code Online (Sandbox Code Playgroud)
现在绝对没有合理的默认方式来获得String一个Parser String.实际上,完全没有办法只用Monad来获得一个String.