<*> 如何从 pure and (>>=) 派生出来?

2023-11-27

class Applicative f => Monad f where
       return :: a -> f a
       (>>=) :: f a -> (a -> f b) -> f b

(<*>)可以从纯粹的和(>>=):

fs <*> as =
    fs >>= (\f -> as >>= (\a -> pure (f a)))

对于线路

fs >>= (\f -> as >>= (\a -> pure (f a)))

我对使用感到困惑>>=。我认为这需要一个函子f a和一个函数,然后返回另一个函子f b。但在这个表情中,我却感到失落。


让我们从我们正在实现的类型开始:

(<*>) :: Monad f => f (a -> b) -> f a -> f b

(正常类型<*>当然有一个Applicative约束,但这里我们尝试使用Monad实施Applicative)

So in fs <*> as = _, fs是“函数 f”(f (a -> b)), and as是一个“f”as".

我们将从绑定开始fs:

(<*>) :: Monad f => f ( a -> b) -> f a -> f b
fs <*> as
  = fs >>= _

如果你真的编译它,GHC 会告诉我们这个洞的类型(_) has:

foo.hs:4:12: warning: [-Wtyped-holes]
    • Found hole: _ :: (a -> b) -> f b
      Where: ‘a’, ‘f’, ‘b’ are rigid type variables bound by
               the type signature for:
                 (Main.<*>) :: forall (f :: * -> *) a b.
                               Monad f =>
                               f (a -> b) -> f a -> f b
               at foo.hs:2:1-45

这就说得通了。莫纳德的>>=需要一个f a左边还有一个函数a -> f b在右边,所以通过绑定f (a -> b)左边的函数在右边得到一个(a -> b)函数“提取”自fs。假设我们可以编写一个函数,可以使用它来返回f b,那么整个绑定表达式将返回f b我们需要满足类型签名<*>.

所以它看起来像:

(<*>) :: Monad f => f ( a -> b) -> f a -> f b
fs <*> as
  = fs >>= (\f -> _)

我们在那里能做什么?我们有f :: a -> b,我们还有as :: f a,我们需要做一个f b。如果你习惯了Functor这是显而易见的;只是fmap f as. Monad暗示Functor,所以这实际上有效:

(<*>) :: Monad f => f ( a -> b) -> f a -> f b
fs <*> as
  = fs >>= (\f -> fmap f as)

我认为这也是一个much更容易理解的方式Applicative可以一般使用以下设施来实现Monad.

So why is your example written using another >>= and pure instead of just fmap? It's kind of harkening back to the days when Monad did not have Applicative and Functor as superclasses. Monad always "morally" implied both of these (since you can implement Applicative and Functor using only the features of Monad), but Haskell didn't always require there to be these instances, which leads to books, tutorials, blog posts, etc explaining how to implement these using only Monad. The example line given is simply inlining the definition of fmap in terms of >>= and pure (return)1.

我会继续打开包装,就好像我们没有一样fmap,这样它就会导致您感到困惑的版本。

如果我们不打算使用fmap结合f :: a -> b and as :: f a,那么我们需要绑定as这样我们就有了一个类型的表达式a申请f to:

(<*>) :: Monad f => f ( a -> b) -> f a -> f b
fs <*> as
  = fs >>= (\f -> as >>= (\a -> _))

在那个洞里我们需要做一个f b,我们有f :: a -> b and a :: a. f a给我们一个b,所以我们需要调用pure把它变成一个f b:

(<*>) :: Monad f => f ( a -> b) -> f a -> f b
fs <*> as
  = fs >>= (\f -> as >>= (\a -> pure (f a)))

这就是这条线正在做的事情。

  1. Binding fs :: f (a -> b)访问f :: a -> b
  2. 在可以访问的函数内部f它具有约束力as访问a :: a
  3. 在可以访问的函数内部a(它仍在可以访问的函数内部f以及),打电话f a做一个b,并致电pure使其成为f b

1 You can implement fmap using >>= and pure as fmap f xs = xs >>= (\x -> pure (f x)), which is also fmap f xs = xs >>= pure . f. Hopefully you can see that the inner bind of your example is simply inlining the first version.

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

<*> 如何从 pure and (>>=) 派生出来? 的相关文章

  • 使用 nix 在 Mac OS X 上由于“架构 x86_64 的未定义符号”而导致“堆栈构建”失败

    首先是错误消息 stack build Linking Users yuzhao stack setup exe cache x86 64 osx tmp Cabal simple mPHDZzAJ 2 2 0 1 ghc 8 4 4 cl
  • Haskell 中的前提条件检查有哪些选项

    这是一个简单的问题 我认为答案很复杂 一个非常常见的编程问题是函数返回某些内容 或者前置条件检查失败 在Java中 我会使用一些抛出异常的断言函数IllegalArgumentException在方法的开头 如下所示 method body
  • 如何让 Show 显示函数名称?

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

    我正在学习 Haskell 所以我尝试实现移动平均函数 这是我的代码 mAverage Int gt Int gt Float mAverage x a fromIntegral k fromIntegral x k lt rawAvera
  • Haskell 中的实例声明

    我有这两个功能 primes sieve 2 where sieve p xs p sieve x x lt xs x mod p gt 0 isPrime number number 1 null x x lt takeWhile x g
  • Haskell 类型系统的细微差别

    我一直在深入了解 haskell 类型系统的本质 并试图了解类型类的要点 我已经学到了很多东西 但我在下面的代码片段上遇到了困难 使用这些类和实例定义 class Show a gt C a where f Int gt a instanc
  • 如何手动推断表达式的类型

    给定 Haskell 函数 head filter fst 现在的问题是如何手动 手动 找到类型 如果我让 Haskell 告诉我我得到的类型 head filter fst Bool b gt Bool b 但我想了解仅使用所用函数的签名
  • C++ 中的函数指针与仿函数

    使用函子和函数指针有什么区别 例如 Functor struct add x int x add x int y x y int operator int y return x y Function int func int x retur
  • 将数据类型设置为 Kind * -> * 这不是函子

    布伦特 约尔吉类型分类百科全书 https www haskell org haskellwiki Typeclassopedia给出以下练习 举一个类型的例子 gt 不能将其制成 的实例Functor 不使用undefined 请告诉我什
  • Haskell 中的 print 是纯函数吗?

    Is print在 Haskell 中是纯函数 为什么或者为什么不 我认为不是 因为它并不总是返回与纯函数应返回的值相同的值 类型的值IO Int并不是真正的Int 它更像是一张纸 上面写着 嘿 Haskell 运行时 请生成一个Int如此
  • Haskell:是的,没有类型类。为什么是整数?

    我有一个关于 GHCi 如何假定整数类型的问题 我正在阅读 Learn you a Haskell 是 否类型的课程 如果您想阅读全文 这里有一个链接 http learnyouahaskell com making our own typ
  • 我应该使用函数还是无状态函子?

    这两段代码做同样的事情 如您所见 它将用于排序函数 哪个更好 我通常写后一种 但我看到一些程序员像以前那样做 struct val lessthan binary function
  • “Eta减少”并不总是在Haskell中举行?

    我发现我可以说 LANGUAGE RankNTypes f1 forall b b gt b gt forall c c gt c f1 f id f HLint 告诉我我可以在这里做 Eta 减少 但是 f2 forall b b gt
  • Haskell 泛化问题(涉及列表理解)

    假设我想知道a上的所有要点 x y 矩形内的平面has 我可以使用列表推导式来计算 如下所示 let myFun2D x y x lt 0 2 y lt 0 2 现在 如果我想为一个人完成同样的事情 x y z 空间 我可以采取同样的方式并
  • 标准的能力

    我发现了一些使用标准的旧例子here http www serpentine com blog 2009 09 29 criterion a new benchmarking library for haskell 看起来好像早在 2009
  • 如何在 Haskell 中制作打勾游戏的图案?

    实现有 2 个参数的函数 ticktick 第一个参数是自然数元组 定义游戏场地的行数和列数 第二个列表包含由玩家 x 和玩家 o 轮流玩的坐标给出的井字游戏比赛的记录 打印游戏的实际状态 其中游戏区域将由字符 和 界定 空方块 以及字符
  • Haskell:Data.Numbers.Primes 库在哪里?

    我尝试导入 Data Numbers Primes import Data Numbers Primes 伦哈斯克尔给了我 5 hs 1 8 Could not find module Data Numbers Primes Use v t
  • 用于遇到 [...] 的 Haskell Parsec 解析器

    我正在尝试使用 Parsec 在 Haskell 中编写一个解析器 目前我有一个可以解析的程序 test x 1 2 3 end 执行此操作的代码如下 testParser do reserved test v lt identifier
  • 在 Haskell 中合并两个列表

    无法弄清楚如何合并两个列表通过以下方式在哈斯克尔 INPUT 1 2 3 4 5 11 12 13 14 OUTPUT 1 11 2 12 3 13 4 14 5 我想提出一个更懒的合并版本 merge ys ys merge x xs y
  • 管道:多个流消费者

    我编写了一个程序来计算语料库中 NGram 的频率 我已经有一个函数 它消耗一串令牌并生成一个订单的 NGram ngram Monad m gt Int gt Conduit t m t trigrams ngram 3 countFre

随机推荐

  • 捕获异步操作的异常

    我在这里阅读有关异步的更多信息 http msdn microsoft com en us library hh873173 v vs 110 aspx 看看这个例子 Task
  • 非凸多边形内最大的圆

    如何找到可以容纳在凹多边形内的最大圆 只要能够实时处理具有约 50 个顶点的多边形 暴力算法就可以 解决这个问题的关键是首先进行观察 适合任意多边形的最大圆的中心是以下点 多边形内部 和 距多边形边缘上任意点最远 为什么 因为圆的边缘上的每
  • F# 中的第一个或默认值

    如何在 F 中编写 FirstOrDefault Linq 查询 我可以在 F 中完全使用 linq to sql 吗 请注意 F 中更惯用的方法可能是使用类似于Seq tryFind而不是使用 LINQ 运算符 尽管它不是替代品 因为它返
  • mongodb 转储多个集合或排除集合版本 2.6

    如何转储多个集合或排除 mongodump 上的集合 mongodb是2 6版本 我现在就是这样做的 mongodump collection map accounts clicks out dumps 您可以使用 排除集合从 MongoD
  • 如何在Python中使用点表示法表示字典?

    我对 python 很陌生 我希望我能做到 访问 a 值的表示法dict 可以说我有test像这样 gt gt gt test dict gt gt gt test name value gt gt gt print test name v
  • 如何使用 faces-redirect 进入 JSF 2.2 流程

    我有一个基本的流程示例 src main webapp index xhtml flow1 flow1 flow xml flow1 xhtml index xhtml 有一个简单的形式 使用参数进入流程
  • 如何修复“客户端身份验证方案‘匿名’禁止 HTTP 请求”

    我在实现与 WCF 服务通信的客户端时遇到一些问题 它是由另一家公司托管的 WCF 因此我无权访问其代码 我使用 Visual Studio 中的连接服务提供程序工具生成客户端代码 以便我可以发出请求 并且一切都在我的本地计算机上正常运行
  • 为什么 npm 将本地包安装在我的主目录中?

    Node js 新手 Windows 10 我npm install ed 一些软件包 没有 g 而在没有的目录中package json npm 将包放入C Users MyName node modules 现在我看到一些奇怪的行为 当
  • 在类中使用 es6 箭头函数[重复]

    这个问题在这里已经有答案了 当我改变一个函数时draw to draw gt 我收到类似 Uncaught SyntaxError Unexpected token 的错误 可能是什么原因 首先 你可能不应该这样做 为什么 嗯 因为箭头函数
  • 将源代码管理中的更改提交到多个分支的实用方法

    使用源代码控制时的常见场景是拥有开发分支和版本化发布分支 我们使用 CVS 以 HEAD 作为开发分支 并命名一个分支 例如 release 6 2 表示产品的当前版本 新功能的开发仅进入开发分支 但错误修复有时必须同时检查到开发分支和当前
  • 有没有办法重定向到另一个 Action 类而不使用 struts.xml

    我在 Struts 应用程序中创建了许多类 我没有检查任何课程是否登录状态 相反 我扩展了一个基本动作类 现在我想在我的基本操作中创建一个预处理程序来检查登录情况并在未登录时进行重定向 我想要这样的东西 public BaseAction
  • 何时调用layoutSubviews方法?

    我正在经历教程其中提到了以下方法 void layoutSubviews 位于CustomerCell m 在应用程序执行期间何时调用此方法 是自动调用的吗 我没有看到任何回调 你会找到你的答案here 编辑 直接从博客复制 init 不会
  • “请求的快照版本太旧。” Firestore 中的错误

    在使用 Firebase 的 Swift 客户端时 从 2 月 9 日开始 我开始看到错误消息 请求的快照版本太旧 在addSnapshotListener的回调中 这个错误是什么意思 我该如何修复它 Thanks None
  • Passport JS“发送后无法设置标头”

    当我使用passport JS成功登录时出现此错误 登录后尝试重定向到主页 执行此操作的代码 app post login passport authenticate local failureRedirect login function
  • 如何限制JTextArea最大行数和列数?

    我在 JScrollPane 中使用 JTextArea 我想限制可能的最大行数和每行的最大字符数 我需要该字符串与屏幕上的完全相同 每行将以 n 结尾 如果后面还有另一行 并且用户将能够在每行中仅插入 X 行和 Y 字符 我试图限制行数
  • 我需要一个最佳算法来找到数字 N 的最大除数。最好是用 C++ 或 C# 语言

    我目前正在使用以下代码 但对于大量数据来说它非常慢 static int divisor int number int i for i number 2 i gt 1 i if number i 0 break return i 首先想到你
  • Rust 是否有相当于 C++ 的 decltype() 的函数来获取表达式的类型?

    我的代码如下所示 macro rules mask bitmap tt count tt for type ty ty gt let bit count std mem size of lt ty gt 8 let dec bit coun
  • 使用C# windows窗体远程关闭PC?

    我正在尝试通过命令提示符使用 C 以编程方式远程关闭 PC 我已经做了一些搜索并找到了此类代码 System Diagnostics Process Start shutdown s 因为它没有指定要关闭的任何电脑 所以我尝试将该代码更改为
  • SQLite-Net 扩展两个实体之间的一对一和一对多关系

    我将 SQLite Net PCL 与 SQLite Net 扩展一起使用 以使用 Xamarin 开发应用程序 在我的模型中 我有两个实体 我们称它们为 A 和 B 它们通过一对一和一对多关系连接 例如 A与B是一对一的关系 A与B也是一
  • <*> 如何从 pure and (>>=) 派生出来?

    class Applicative f gt Monad f where return a gt f a gt gt f a gt a gt f b gt f b lt gt 可以从纯粹的和 gt gt fs lt gt as fs gt