在 Maybe 类型上应用函数?

2024-02-18

Haskell 新手,我不知道如何将函数 (a -> b) 应用于列表 [也许 a] 并获取 [也许 b]

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

该函数应该做与 map 完全相同的事情,将函数 f 应用于 Maybe 语句列表,如果它只是它,它会返回一个 f Just,如果它是一个 Nothing,则返回一个 Nothing。 像下面的示例一样,我想在以下 List 的每个 Element 上添加 +5 :

[Just 1,Just 2,Nothing,Just 3]

and get

[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)

If the Maybe包含一个值,mapMaybe适用f如果它不包含值,那么我们只返回一个空值Maybe.

但我们有一个list of Maybes,所以我们需要申请mapMaybe给他们每个人。

mapMaybes :: (a -> b) -> [Maybe a] -> [Maybe b]
mapMaybes f ms = [mapMaybe f m | m <- ms]

这里我使用列表理解来评估mapMaybe f m对于每个m in ms.


现在介绍更先进的技术。将函数应用于容器中的每个值的模式由Functor类型类。

class Functor f where
    fmap :: (a -> b) -> f a -> f b

A type f is a Functor如果你可以编写一个函数来获取函数a to b,并将该函数应用于f充满a得到一个f充满bs。例如,[] and Maybe都是Functors:

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的版本fmapmapMaybe我在上面写了,并且[]的实现使用列表理解来应用f到列表中的每个元素。

现在,要写mapMaybes :: (a -> b) -> [Maybe a] -> [Maybe b],您需要使用以下命令对列表中的每个项目进行操作[]的版本fmap,然后对个体进行操作Maybes using 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],它发送到[]'s Functor实例。里面的一个是(a -> b) -> Maybe a -> Maybe b.


还有一个附录 - 尽管这相当深奥,所以如果您不理解这里的所有内容,请不要担心。我只是想让你尝尝我认为很酷的东西。

这条“链fmaps”风格(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 fmaps 可以让您映射级别的元素n的结构。康纳尔·埃利奥特称这种风格为“语义编辑器组合器” http://conal.net/blog/posts/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图书馆。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Maybe 类型上应用函数? 的相关文章

  • 如何获取调用函数的“this”值?

    如果我有一个这样的函数 function foo this console log this function bar bar prototype func function foo this var test new bar test f
  • 导入 Haskell 模块

    我是哈斯克尔的新手 为什么当我尝试使用时Days from Data Time我收到此错误 Could not find module Data Time It is a member of the hidden package time
  • 如何为强制长度为 2^n 的向量类型定义可用的 Applicative 实例

    对于某些应用程序 我需要长度为 2 n 的向量 为了强制某些操作的长度匹配 我使用 ist 应用实例定义了我的类型 如下所示 LANGUAGE GADTs DataKinds FlexibleInstances FlexibleContex
  • 如何让 Show 显示函数名称?

    作为一个让我熟悉 Haskell 的简单练习 在 Youtube 上闲逛并偶然进入美国倒计时游戏节目之后 我想为数字游戏制作一个求解器 你得到 6 个数字 需要将它们与 为了得到给定的结果 到目前为止我所得到的是非常脑死亡的 let ope
  • 如何将函数应用于多个 pandas 数据框

    我有多个数据框 df1 df2 df3 dfn 它们具有相同类型的数据 但来自无法连接的不同描述符组 现在我需要手动将相同的函数应用于每个数据帧 如何将相同的函数应用于多个数据框 pipe https pandas pydata org p
  • 如何从 haskell 中的 IOError 获取 errno?

    我在 haskell 平台上 GHC 6 12 1 作为 apt get 安装在 Debian Squeeze 上 鉴于我需要在与最初引发它的线程不同的线程上使用它 如何从 IOError 中获取底层 errno 我需要这个的原因是因为我正
  • 这个记忆的斐波那契函数是如何工作的?

    在我正在做的函数式编程课程的当前练习作业中 我们必须制作给定函数的记忆版本 为了解释记忆化 给出以下示例 fiblist fibm x x lt 0 fibm 0 0 fibm 1 1 fibm n fiblist n 1 fiblist
  • Javascript 中“是……的实例”是什么意思?

    这个问题的答案 JavaScript 函数的原型属性的初始值是多少 https stackoverflow com questions 4073677 what is the initial value of a javascript fu
  • Haskell 下划线与显式变量

    我已经学习 Haskell 几个星期了 我有一个关于下划线的使用的问题 作为函数参数 我认为用一个具体的例子来问我的问题会更好 假设我想定义一个函数 根据提供的索引提取列表的元素 是的 我意识到 已经是预先定义的 我可以定义该函数的两种方法
  • Haskell scala 互操作性

    我是 Scala 初学者 来自面向对象范式 在了解 Scala 的函数式编程部分时 我被引导到 Haskell 纯函数式编程语言 探索 SO 问题答案 我发现 Java Haskell 具有互操作性 我很想知道 Scala Haskell
  • 带有 UnboundLocalError 的本地和全局引用

    我不太明白为什么代码 def f print s s foo f 运行得很好但是 def f print s s bar s foo f 给我 UnboundLocalError 我知道我可以通过声明来解决这个问题s作为函数内的全局变量或简
  • 如何确定函数是否不返回任何内容?

    有没有办法在 PHP 中使用反射或其他方法来做到这一点 function a return null function b a a null b b null 如果您没有显式返回某些内容 则函数将返回null默认情况下 这就是 PHP 中函
  • swift 中闭包和函数作为参数的区别

    我有将近 4 年的 Objective C 经验 并且是 swift 的新手 我试图从 Objective C 的角度理解 swift 的概念 所以如果我错了 请指导我 在目标 c 中 我们有块 可以稍后异步执行的代码块 这绝对是完全合理的
  • 使用 FoldLine 解析多个块

    对于这个简化的问题 我试图解析一个如下所示的输入 foo bar baz quux woo hoo xyzzy glulx into foo bar baz quux woo hoo xyzzy glulx 我尝试过的代码如下 import
  • Haskell 中的中缀运算符优先级

    对于以下 Haskell 表达式 返回 a gt gt f 应该读作 返回a gt gt f or 返回 a gt gt f 这里的相关规则是什么 规则始终是函数应用程序的优先级高于任何运算符 因此 return a gt gt f 被解析
  • 标准的能力

    我发现了一些使用标准的旧例子here http www serpentine com blog 2009 09 29 criterion a new benchmarking library for haskell 看起来好像早在 2009
  • 全局变量声明

    我是 Python 的初学者 并且已经处理过全局变量的概念 当我以为我理解了这个概念时 我看到了一段简短的代码 证明我错了 message global def enclosure message enclosure def local g
  • 根据 R 数据框中的名称对列进行平均

    我想知道是否有一种有效的方法来获取每组的平均值类似命名的列谁的名字结尾为 1S and 2S ex ex1S ex2S at time 1并取每组的平均值类似命名的列谁的名字结尾为 1C or 2C ex ex1C ex2C at time
  • 简单 Haskell Monad - 随机数

    我正在尝试扩展代码这个帖子 https stackoverflow com questions 3944170 haskell and state 接受的答案 允许我能够基于以种子作为参数的函数 randomGen 调用 randomGen
  • 有没有更好的方法将 UTC 时间转换为大纪元时间?

    我想将文件的修改时间设置为从 exif 数据获取的时间 为了从 exif 获取时间 我发现 Graphics Exif getTag Exif gt String gt IO Maybe String 要设置文件修改时间 我发现 Syste

随机推荐