gpt4 book ai didi

haskell - 在 haskell 中为 monad 创建过滤函数

转载 作者:行者123 更新时间:2023-12-02 21:28:26 27 4
gpt4 key购买 nike

假设我们有一个过滤函数。

filterM::Monad m => (a -> m Bool) -> [a] -> m [a]

假设我们的 a -> m Bool 函数如下:

p :: Integer -> Maybe Bool
p n | n > 0 = Just True
| n < 0 = Just False
| otherwise = Nothing

在示例中,m 是 Maybe。

我想创建 filterM 函数,以便:

filterM p [2,−4,1] = Just [2,1]

filterM p [2,0,−4,1] = Nothing

本质上这个filterM是过滤器,但是针对monad。

这是我的实现。它不起作用,我有几个问题。

filterM p [] = pure []
filterM p (x : xs) | p x == Just True = x : (filterM p xs)
| p x == Just False = filterM p xs
| otherwise = Nothing

首先,为什么它不起作用。它说无法将类型 m 与 Maybe m 是刚性类型变量匹配。

  Expected type: m Bool
Actual type: Maybe Bool

在我的函数中,我将“也许”硬编码为 m,但如何使其更通用?

我会使用 do 表示法,但它似乎不是最好的选择,因为存在递归。

最佳答案

有两个问题。首先是您已经给出了类型签名:

filterM :: Monad m => (a -> m Bool) -> [a] -> m [a]

然后定义 filterM ,其中 m 专门用于 Maybe (因为您使用 JustNothing 在你的定义中)。当 Haskell 推断出 m 必须是 Maybe 时,这会导致错误。类型 m 是“刚性”的,因为它是由您在类型签名中提供的,并且刚性类型必须保持通用;如果它们的多态性低于指定值,则会发生冲突。您可以通过编写以下内容来生成类似的错误消息:

badId :: a -> Int
badId x = x

显然,aInt,因此刚性(程序员指定的)类型 a 被确定为匹配 Int 在类型检查期间。

但是,即使您修复了类型签名:

filterM :: (a -> Maybe Bool) -> [a] -> Maybe [a]
filterM p [] = pure []
filterM p (x : xs) | p x == Just True = x : (filterM p xs)
| p x == Just False = filterM p xs
| otherwise = Nothing

您仍然会收到错误消息。您在代码中混淆了单元操作和值。表达式中:

x : filterM p xs

您正在将运算符 (:)::b -> [b] -> [b] 应用于类型 aMaybe [a ],因此它不会进行类型检查(“无法将预期类型 也许 [a] 与实际类型 [a] 匹配。”)

您需要将 x : filterM p xs 替换为以下内容:

case filterM p xs of
Nothing -> Nothing
Just xs' -> Just (x : xs')

关于haskell - 在 haskell 中为 monad 创建过滤函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55562988/

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