function - 在 Maybe 类型上应用函数?

标签 function haskell maybe

Haskell 新手,我不知道如何将函数 (a -> b) 应用到列表 [Maybe a] 并获得 [Maybe b]

maybeX:: (a -> b) -> [Maybe a] -> [Maybe b]

该函数应该与 map 执行完全相同的操作,将函数 f 应用于 Maybe 语句列表,如果它 Just 它返回我一个 f Just 并且如果它是一个 Nothing 则只是一个 Nothing。
像以下示例一样,我想在以下 List 的每个元素上添加 +5 :
[Just 1,Just 2,Nothing,Just 3]

并得到
[Just 6,Just 7,Nothing,Just 8]

真的想弄清楚这一点,我尝试了很多,但它似乎总是我不知道这种 Maybe 数据类型的工作方式..
谢谢你的帮助!

最佳答案

让我们从定义如何作用于单个 Maybe 开始。 ,然后我们将其扩展到整个列表。

mapMaybe :: (a -> b) -> Maybe a -> Maybe b
mapMaybe f Nothing = Nothing
mapMaybe f (Just x) = Just (f x)

如果 Maybe包含一个值,mapMaybe申请 f给它,如果它不包含一个值,那么我们只返回一个空的 Maybe .

但是我们有一个列表 Maybe s,所以我们需要申请mapMaybe给他们每个人。
mapMaybes :: (a -> b) -> [Maybe a] -> [Maybe b]
mapMaybes f ms = [mapMaybe f m | m <- ms]

这里我使用列表推导来评估 mapMaybe f m对于每个 mms .

现在换一种更先进的技术。 Functor 捕获了将函数应用于容器中的每个值的模式。类型类。
class Functor f where
    fmap :: (a -> b) -> f a -> f b

A型fFunctor如果您可以编写一个函数,该函数从 a 获取函数至b , 并将该函数应用于 f满满的a s 获取 f满满的b s。例如,[]Maybe都是Functor年代:
instance Functor Maybe where
    fmap f Nothing = Nothing
    fmap f (Just x) = Just (f x)

instance Functor [] where
    fmap f xs = [f x | x <- xs]
Maybe fmap 的版本与 mapMaybe 相同我在上面写了,[]的实现使用列表推导来应用 f到列表中的每个元素。

现在,写mapMaybes :: (a -> b) -> [Maybe a] -> [Maybe b] ,您需要使用 [] 对列表中的每个项目进行操作fmap 的版本, 然后对个体 Maybe 进行操作使用 Maybe fmap 的版本.
mapMaybes :: (a -> b) -> [Maybe a] -> [Maybe b]
mapMaybes f ms = fmap (fmap f) ms
-- or:
mapMaybes = fmap . fmap

请注意,我们实际上调用了两个不同的 fmap这里的实现。外层是fmap :: (Maybe a -> Maybe b) -> [Maybe a] -> [Maybe b] , 发送到 []Functor实例。内页是(a -> b) -> Maybe a -> Maybe b .

还有一个附录 - 虽然这很深奥,所以如果你不明白这里的所有内容,请不要担心。我只是想让你尝尝我认为很酷的东西。

这种“fmap s 链”样式 (fmap . fmap . fmap ...) 是深入钻取结构的多层的常用技巧。每个fmap类型为 (a -> b) -> (f a -> f b) , 所以当你用 (.) 组合它们时你正在构建一个高阶函数。
fmap        :: Functor g              =>             (f a -> f b) -> (g (f a) -> g (f b))
fmap        :: Functor f              => (a -> b) -> (f a -> f b)
-- so...
fmap . fmap :: (Functor f, Functor g) => (a -> b)          ->         g (f a) -> g (f b)

因此,如果您有一个仿函数(仿函数...)的仿函数,那么 n fmap s 将允许您在结构的第 n 级映射元素。 Conal Elliot 称这种风格为 "semantic editor combinators" .

该技巧也适用于 traverse :: (Traversable t, Applicative f) => (a -> f b) -> (t a -> f (t b)) ,是一种“有效的fmap”。
traverse            :: (...) =>               (t a -> f (t b)) -> (s (t a) -> f (s (t b)))
traverse            :: (...) => (a -> f b) -> (t a -> f (t b))
-- so...
traverse . traverse :: (...) => (a -> f b)            ->           s (t a) -> f (s (t b))

(我省略了 => 之前的位,因为我用完了水平空间。)因此,如果您有一个可遍历的(可遍历的...),您只需编写即可对第 n 级的元素执行有效的计算traverse n次。像这样组成遍历是 lens 背后的基本思想。图书馆。

关于function - 在 Maybe 类型上应用函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47498896/

相关文章:

c - 为什么函数在没有指定返回类型的情况下有返回值?

python - 在 python 中使用 Arcpy 具有两个 for 循环的非常慢的函数

haskell - 带有符号字符的函数名称使谷歌搜索变得困难

sql - 使用Haskell的postgres-simple库执行多行插入时如何修复 "operator does not exist: text = uuid"?

haskell - Haskell 中 isNothing 和 (== Nothing) 的区别?

haskell - 使用Maybe's从一系列ADT中检索值

javascript - 调用存储在变量中的方法而不指定 this

javascript - 如何编写一个 JS 函数来在 <li> 类中查找 img 并将该图像作为 li 的 css 中的背景图像值?

string - 为什么 Haskell 在处理字符串时分配大量内存?

haskell - 有没有一种无点的方法可以将条件检查转换为 Maybe 类型的输入?