是用 Monad 的 Applicative 来定义 Functor 更好,还是反之亦然?

2023-12-24

这是一个一般性问题,与任何一段代码无关。

假设你有一个类型T a可以给出一个实例Monad。因为每个单子都是一个Applicative通过分配pure = return and (<*>) = ap,然后每个应用程序都是一个Functor via fmap f x = pure f <*> x,定义你的实例是否更好Monad首先,然后简单地给出T的实例Applicative and Functor?

对我来说感觉有点落后。如果我做数学而不是编程,我会认为我会首先证明我的对象是一个函子,然后继续添加限制,直到我也证明它是一个单子。我知道 Haskell 只是受到范畴论的启发,显然,构建证明时使用的技术并不是编写有用程序时使用的技术,但我想从 Haskell 社区获得意见。是不是比较好从Monad向下Functor?或来自Functor up to Monad?


我倾向于写和看写的Functor先实例。加倍如此,因为如果你使用LANGUAGE DeriveFunctor那么编译指示data Foo a = Foo a deriving ( Functor )大部分时间都在工作。

棘手的部分是当你的实例达成一致时Applicative可以比你的更笼统Monad。例如,这是一个Err数据类型

data Err e a = Err [e] | Ok a deriving ( Functor )

instance Applicative (Err e) where
  pure = Ok
  Err es <*> Err es' = Err (es ++ es')
  Err es <*> _       = Err es
  _      <*> Err es  = Err es
  Ok  f  <*> Ok  x   = Ok (f x)

instance Monad (Err e) where
  return = pure
  Err es >>= _ = Err es
  Ok  a  >>= f = f a

上面我定义了实例Functor-to-Monad顺序,并且单独来看,每个实例都是正确的。不幸的是,Applicative and Monad实例不对齐:ap and (<*>)明显不同(>>) and (*>).

Err "hi" <*>  Err "bye" == Err "hibye"
Err "hi" `ap` Err "bye" == Err "hi"

出于敏感性目的,特别是当 Applicative/Monad 提案掌握在每个人手中时,这些应该保持一致。如果你定义了instance Applicative (Err e) where { pure = return; (<*>) = ap }然后他们will align.

但最后,你可能能够仔细地梳理出不同之处Applicative and Monad这样他们就会以良性的方式表现得不同——比如有一个更懒惰或更高效的人Applicative实例。这种情况实际上经常发生,我觉得陪审团对于“良性”的含义以及您的实例应该在什么样的“观察”下保持一致还有些不明确。也许对此最广泛的使用是在 Facebook 的 Haxl 项目中,其中Applicative实例是更加并行化Monad例如,因此效率更高,但代价是一些相当严重的“未观察到的”副作用。

无论如何,如果它们不同,请记录下来。

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

是用 Monad 的 Applicative 来定义 Functor 更好,还是反之亦然? 的相关文章

  • Haskell 中的参数数量和无点 [重复]

    这个问题在这里已经有答案了 对于多重模式匹配 不同数量的参数是不可能的 即使是无点的 foo True b b 2 foo id 例如 不起作用 但 foo True 2 foo id 做 有时我们只能在函数的一部分使用 point fre
  • 测试列表是否已排序

    在 haskell 中找到最小列表确实很容易 foldl1 min 9 5 7 3 7 4 6 10 给我3 我更换了min with lt 测试列表是否已排序 foldl1 lt 9 5 7 3 7 4 6 10 我收到此错误消息 No
  • 结构上强制的自由替代,没有左派分配性

    有一个不错的免费替代品 http hackage haskell org package free 4 12 4 docs Control Alternative Free html在伟大的free包 它将函子提升到左分配替代方案 也就是说
  • 当单态限制打开*时,如何解决歧义问题?

    因此 在学习 Haskell 时 我很快就遇到了可怕的单态限制 在 ghci 中 Prelude gt let f print show Prelude gt f 5
  • Control.Arrow 与 Data.Tuple.Extra

    我经常使用以下功能Data Tuple Extra图书馆 first second and both 有等效的 函数Control Arrow 其实我更喜欢Data Tuple Extra因为我完全迷失了文档Control Arrow 使用
  • Haskell:如何创建将函数应用于元组项的最通用函数

    这是一个个人练习 旨在更好地理解 Haskell 类型系统的局限性 我想创建最通用的函数 将某些函数应用于 2 条目元组中的每个条目 例如 applyToTuple fn a b fn a fn b 我试图让这个函数在以下每种情况下都起作用
  • 在 Haskell 中对单位的组成(例如英寸、美元等)进行建模

    跟进自我之前的一个问题 https stackoverflow com q 73375273 222529 我问如何创建一个可以对单元进行建模的类型 例如Inch 作为 Haskell 中的一种类型 我现在面临的问题是如何对该单元和其他单元
  • 如何在 blaze-html 中渲染 blaze-svg 标记

    我想将使用 blaze svg 生成的 svg 图直接包含在使用 blaze html 生成的 html 中 两者都基于 blaze markup 所以我希望它很容易 diagram1 Svg diagram1 try1 Html try1
  • Haskell,范围缩小到无步骤[重复]

    这个问题在这里已经有答案了 为什么在 Haskell 中工作范围不能降低到没有步骤 7 1 gt 但只工作这个 7 6 1 gt 7 6 5 4 3 2 1 Haskell 无法知道您想要执行 1 除非您给出提示 在某些情况下 您可能需要一
  • Haskell printf 转字符串

    Haskell 中有等效的 sprintf 吗 我需要将双精度值转换并格式化为字符串 有没有其他方法而不使用printf什么样的功能 主要问题是要避免 Prelude gt putStrLn myDoubleVal 1 7944444444
  • Haskell 二进制解析

    我一直在尝试在 haskell 中实现一个协议解析器 而且我对这门语言还很陌生 特别是当涉及到 monad 时 我一直在使用binary 0 5 0 2 并描述了协议的标头和所有有效负载 我想要解析的消息如下所示 header payloa
  • 如何将只缓存某些内容的字段添加到ADT?

    我经常需要向 ADT 添加字段 仅记住一些冗余信息 但我还没有完全弄清楚如何又好又高效地做到这一点 说明问题的最好方法是举个例子 假设我们正在使用无类型 lambda 项 type VSym String data Lambda Var V
  • GHC 是否使用存在类型的动态调度?

    下面的代码是否使用了 C 或 Java 中所理解的动态调度 据我了解 在最后一行 编译器不可能在编译时知道要调用哪个 实现 但代码会编译并产生正确的结果 有人可以解释一下 这背后有什么样的实现 例如 vptr 吗 LANGUAGE Exis
  • 我应该使用镜头中的什么来按索引构建只读吸气剂?

    我有一个内部细节被隐藏的类型 我想提供某种镜头 可以在特定索引处读取所述类型的元素 但是not修改它们 一个Ixed我的类型的实例似乎没有做我想要的事情 因为它明确允许修改 尽管不允许插入或删除 如果我想允许只读索引 我不确定我使用什么 如
  • Haskell 中的相互递归求值器

    Update 我已经添加一个答案 https stackoverflow com questions 3524485 mutually recursive evaluator in haskell 4504200 4504200这描述了我的
  • 反应性香蕉时间延迟

    我已经查阅了文档反应香蕉 http hackage haskell org package reactive banana 而且我找不到指定明确时间延迟的方法 举例来说 我想采取Event t a并将其所有发生的事件移至未来 1 秒 或获取
  • 带有查询参数的渲染 url

    无法找到简单问题的解决方案 答案应该是显而易见的 如何在 hamlet 模板中使用查询参数渲染 url I e ItemsR 将生成http localhost 3000 items我如何生成类似的东西http localhost 3000
  • 为什么 exceptT 没有 MonadMask 实例?

    爱德华 克梅特例外情况图书馆不提供单子掩码 https www stackage org haddock lts 7 18 exceptions 0 8 3 Control Monad Catch html t MonadMask实例为Ex
  • 管道中缺少 ResourceT 实例

    我在尝试使用时遇到奇怪的错误ResourceT http hackage haskell org package conduit 1 0 9 1 docs Data Conduit html t 3aResourceT来自管道 1 0 9
  • 类型级编程有哪些示例? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我不明白 类型级编程 是什么意思 也无法使用Google找到合适的解释 有人可以提供一个演示类型级编程的示例吗 范式的解释和 或定义将

随机推荐