gpt4 book ai didi

haskell - 为什么 `guarded False = fail "跳过“`类型检查?

转载 作者:行者123 更新时间:2023-12-02 17:43:00 24 4
gpt4 key购买 nike

我正在关注 Real World Haskell 这本书。在有关 Monad 的章节中,他们给出了一个简单的示例,使用列表 monad 来计算满足 x * y == n 的所有数字对 (x, y)。

他们的解决方案是:

multiplyTo :: Int -> [(Int, Int)]
multiplyTo n = do
x <- [1..n]
y <- [x..n]
guarded (x * y == n) $
return (x, y)

guarded :: Bool -> [a] -> [a]
guarded True xs = xs
guarded False _ = []

但我想知道是否可以对任何单子(monad)重申guarded

由于列表 monad 中的 failfail _ = [],我想我可以这样做:

guarded :: (Monad m) => Bool -> m a -> m a
guarded True = id
guarded False = fail "skipped"

但是,这实际上在 ghci 中失败了:

*Main> multiplyTo 24
*** Exception: skipped

我有一种无法完全解释的预感。这两个版本的工作原理:

guarded :: (Monad m) => Bool -> m a -> m a
guarded True = id
guarded False = \s -> fail "skipped"

guarded :: (Monad m) => Bool -> m a -> m a
guarded True xs = xs
guarded False _ = fail "skipped"

fail "skipped" 的类型为 Monad m => m a,而 guarded False 的类型为 Monad m => m a -> m a。那么我的第一个定义的 guarded 类型检查怎么可能呢?

最佳答案

你被有争议的函数单子(monad)实例绊倒了(实际上这在 Haskell 社区中并没有那么有争议,但我个人认为如果它不存在我们可能会更好)以及毫无争议的失败 fail 方法。

查看类型:

guarded False
= fail "skipped" :: m a -> m a
≡ (fail :: String -> (m a -> m a)) "skipped"
≡ (fail :: String -> F (m a)) "skipped" -- with `type F x = m a -> x`

即,您在 (->) (m a) monad 上调用 fail,并且 does not define a custom fail implementation ,所以它defaults to the error one

  fail        :: String -> ((->) r) a
fail s = errorWithoutStackTrace s

请注意,如果您从函数中删除 Monad m 约束,那么它甚至会进行类型检查,因为 fail 不使用该 monad。

你的函数的正确概括是

guarded :: Alternative f => Bool -> f a -> f a
guarded True = id
guarded False = const empty

如果我错误地忘记了 const,这不会进行类型检查,因为函数不是 Alternative 的实例。

关于haskell - 为什么 `guarded False = fail "跳过“`类型检查?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50989541/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com