如何从一元行动中提取价值

ДМИ*_*КОВ 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,即从无中生有的东西.你不能这样做.

  • @Jan:另一方面,这两个功能都不是一个好主意.`fromJust`是可怕的,最好不存在. (15认同)
  • 另一方面,这一事实并不妨碍"从......存在".它返回"Just"的内容,并在"Nothing"的情况下引发异常.你的`Null` monad可以简单地在调用这样的虚构monad展开函数时引发异常. (4认同)
  • @CAMcCann我+1你的评论部分是因为`fromJust`不好......但主要是因为你使用了“另一只手”。 (3认同)
  • @GyörgyAndrasek:即使在这种情况下,我也建议使用`fromMaybe(错误“UI 定义文件丢失”)` 而不是`fromJust`。 (2认同)

Car*_*arl 14

这不存在,因为它Monad是一种组合模式,而不是一种分解模式.您可以随时将更多部分与其定义的界面放在一起.它没有说任何分开的事情.

问为什么你不能拿出一些东西就像问为什么Java的Iterator接口不包含一个方法来添加迭代的元素.它不是Iterator界面的用途.

关于具有一种提取函数的特定类型的论证遵循完全相同的方式.某些特定的实现Iterator可能具有一个add功能.但是因为它不是什么Iterator,所以在某个特定实例上存在该方法是无关紧要的.

而存在fromJust也同样无关紧要.这不是行为Monad旨在描述的一部分.其他人提供了许多类型的例子,其中没有价值extract可供使用.但那些类型仍然支持其预期的语义Monad.这个很重要.这意味着这Monad是一个比你给予赞誉的更通用的界面.


Lui*_*las 9

假设有这样一个功能:

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将不是纯粹的功能.

  • [unsafePerformIO](http://hackage.haskell.org/package/base-4.7.0.1/docs/System-IO-Unsafe.html#v%3aunsafePerformIO)就是这样做的. (2认同)

Dan*_*ton 6

是否有带签名的内置函数:: (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来说它可能意味着什么都没有,有时候,它只是不安全.

  • 我不知道`Monad m => ma - > a`是否缺乏任何不适用于`>> =`或`return`或`fail`的含义.你总是可以说,在知道`m`提供的包含在Monad类型类中的完整实现之前,操作的"含义"没有明确定义.对于列表示例,类型为"Monad m => ma - > a"的函数很可能意味着您建议的任何内容 - *****可能*有效.您可以随时使用`newtype`来调整*your*应用程序的行为,但是否认这样做的机会似乎太严重了. (2认同)

Cub*_*bic 5

因为它可能毫无意义(实际上,在许多情况下确实毫无意义).

例如,我可能会像这样定义一个Parser Monad:

data Parser a = Parser (String ->[(a, String)])
Run Code Online (Sandbox Code Playgroud)

现在绝对没有合理的默认方式来获得String一个Parser String.实际上,完全没有办法只用Monad来获得一个String.