为什么 Kleisli 不是 Monoid 的一个实例?

2024-06-24

如果您希望附加两个类型 (a -> m b) 的函数,以便只得到一个附加两个结果的相同类型的函数,您可以使用 Kleisli 来执行此操作:

instance (Monad m, Monoid b) => Monoid (Kleisli m a b) where
    mempty = Kleisli (\_ -> return mempty)
    mappend k1 k2 =
        Kleisli g
            where
                g x = do
                    r1 <- runKleisli k1 x
                    r2 <- runKleisli k2 x
                    return (r1 <> r2)

然而,目前没有这样的实例定义Control.Arrow。 在 Haskell 中,我经常怀疑有一个很好的理由,但找不到哪个理由。

Note

这个问题与this one https://stackoverflow.com/questions/18925045/why-there-isnt-a-functor-instance-for-kleisli-in-control-arrow。然而,对于 Monoid,我看不到定义实例的方法,例如:

instance (Monad m, Monoid b) => Monoid (a -> m b) where
    [...]

因为已经有一个实例:

instance Monoid b => Monoid (a -> b) where
    [...]

在图书馆设计业务中,我们面临着一个选择点,我们选择在我们的集体政策上不完全一致(或缺乏集体政策)。

Monoid的实例Monad (or Applicative) 类型构造函数可以通过多种方式出现。逐点提升始终可用,但我们没有定义

instance (Applicative f, Monoid x) => Monoid (f x) {- not really -} where
  mempty         = pure mempty
  mappend fa fb  = mappend <$> fa <*> fb

请注意,instance Monoid (a -> b)就是这样的逐点提升,所以逐点提升(a -> m b)每当幺半群实例发生时,就会发生m b对幺半群进行逐点提升b.

一般来说,我们不进行逐点提升,不仅因为它会阻止其他Monoid其载体恰好是应用类型的实例,也因为其结构f通常被认为比x。一个关键的例子是free幺半群,更广为人知的名称是[x],这是一个Monoid by [] and (++),而不是逐点提升。幺半群结构来自列表包装,而不是来自包装的元素。

我更喜欢的经验法则确实是优先考虑类型构造函数中固有的幺半群结构,而不是逐点提升或特定类型实例化的幺半群结构,例如组合幺半群a -> a。这些可以而且确实得到newtype包装纸。

关于是否Monoid (m x)应与MonadPlus m每当两者都存在时(并且类似地Alternative)。我的感觉是唯一的好处MonadPlus实例是一个副本Monoid实例,但其他方面有所不同。尽管如此,图书馆在这件事上并不一致,尤其是在以下问题上(许多读者已经看到我的这个老麻烦了)......

...的幺半群实例Maybe,它忽略了我们经常使用的事实Maybe对可能的失败进行建模,并观察到,如果半群还没有中性元素,则可以使用插入额外元素的相同数据类型想法来为半群提供中性元素。这两种结构产生了同构类型,但它们在概念上并不同源。 (Edit更糟糕的是,这个想法的实施很笨拙,例如Monoid约束,当只有一个Semigroup是需要的。我想看看Semigroup-延伸至-Monoid想法实现了,但是not for Maybe.)

回到Kleisli特别是,我们有三个明显的候选实例:

  1. Monoid (Kleisli m a a) with return和克莱斯利组成
  2. MonadPlus m => Monoid (Kleisli m a b)起重mzero and mplus逐点结束->
  3. Monoid b => Monoid (Kleisli m a b)提升幺半群结构b over m then ->

我预计不会做出任何选择,只是因为尚不清楚该做出哪个选择。我犹豫是否要这么说,但我的投票是 2,优先考虑来自的结构Kleisli m a超过来自的结构b.

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

为什么 Kleisli 不是 Monoid 的一个实例? 的相关文章

  • Haskell 中实例声明的参数顺序切换

    我想进行实例声明 但自由类型变量不是最后一个变量 例如 我有一个类声明 class Poppable m where tryPop m a gt Maybe a m a 现在我想让 Q PSQ 优先级队列 成为 Poppable 的实例 具
  • 在 Haskell 中创建 100 万个线程需要多长时间?

    据我了解 Haskell 有绿色线程 但它们的重量有多轻 是否可以创建100万个线程 或者 100 000 个线程需要多长时间 from here http www reddit com r programming comments a4n
  • Haskell 中的所有图形和 Web 库是如何实现的?

    我才开始学习Haskell 我读到它是一种纯函数式语言 其中的所有内容都是不可变的 因此 输入输出 写入和读取数据库之类的事情会导致状态的可变性 我知道 Haskell 中有一种叫做 monad 的东西 它允许在 Haskell 中使用命令
  • 用纯函数式语言保持状态

    我正在尝试弄清楚如何执行以下操作 假设您正在开发直流电机的控制器 您希望让它以用户设置的特定速度旋转 def set point ref sp 90 while true let curr read speed controller set
  • 计算出类型索引的自由 monad 的细节

    我一直在使用免费的 monad 来构建 DSL 作为语言的一部分 有一个input命令 目标是在类型级别反映输入原语期望的类型 以提高安全性 例如 我希望能够编写以下程序 concat Action String String concat
  • `arr fst` 是如何自然变换的?

    I asked 这个问题 https stackoverflow com q 62733726 11143763不久以前 这是关于以下箭头定律 arr fst first f f arr fst Category k gt k b c gt
  • 如何从有向无环图导出FRP?

    我目前正在研究我的下一个项目 目前处于预规划阶段 因此这个问题只是为了了解现有技术的概述 Setup 我有一个具有多个输入和输出的有向无环图 DAG 现在考虑人工神经网络 处理这种结构的常见方法是在每个 时间 步骤上处理整个网络 我相信这是
  • 对参数进行排序以利用柯里化

    我最近两次重构代码以更改参数的顺序 因为代码太多 黑客喜欢flip or x gt foo bar x 42正在发生 在设计函数签名时 哪些原则可以帮助我充分利用柯里化 对于轻松支持柯里化和部分应用的语言 有一系列令人信服的论点 最初来自
  • Haskell 中是否可以部分应用第 n 个参数?

    我很好奇是否可以写一个函数apply nth它接受一个函数 参数的数量以及该参数的值 然后返回一个新的 部分应用的函数 我的感觉是 由于类型系统的原因 这是不可能的 但我无法给出令人满意的答案 我也无法提出工作类型签名 如果语言的类型更加松
  • 为什么 Kleisli 不是 Monoid 的一个实例?

    如果您希望附加两个类型 a gt m b 的函数 以便只得到一个附加两个结果的相同类型的函数 您可以使用 Kleisli 来执行此操作 instance Monad m Monoid b gt Monoid Kleisli m a b wh
  • 我可以在程序内更改堆栈大小限制吗?

    我可以通过传递配置 GHC 编译的 Haskell 程序的最大堆栈大小 RTS Kn到它 在哪里n是某个数字 有没有办法在程序内更改此设置 我想对各种函数的堆栈消耗进行基准测试 因此尝试在各种限制下运行它 捕获StackOverflow例外
  • 无法让 wxHaskell 在 Mac 上从 ghci 工作

    我正在尝试跑步一个例子 http www haskell org haskellwiki WxHaskell Quick start Hello world in wxHaskell using EnableGUI function htt
  • Haskell 中的随机枢轴快速排序

    是否有可能在 Haskell 中实现快速排序 使用 RANDOM PIVOT 但仍然有一个简单的Ord a gt a gt a 签名 我开始了解 Monad 目前 我将 monad 解释为某种 命令模式 这对于 IO 非常有用 所以 我知道
  • 为什么阴谋集团重新安装“总是危险的”?

    使用 Cabal 重新安装软件包时 通常会看到以下警告 警告 请注意 重新安装总是很危险的 无论如何继续 此消息背后的一些原因是什么 目前 重新安装软件包意味着破坏性地覆盖已安装的软件包 如果旧包对系统有任何反向依赖性 它们将不再工作 为了
  • 如何编写将布尔值返回到一个函数的函数

    我在这里发现了一个类似的问题 它问了几乎相同的问题 但又不完全一样 我的问题是如何将 a gt Bool 类型的函数列表组合成一个也是 a gt Bool 的函数 Ex compose a gt Bool gt a gt Bool comp
  • Haskell 程序查找列表中元素的位置

    我需要编写一个函数来查找列表中一个特定元素的位置 我是这样写的 findPos list elt list 1 head list elt 0 otherwise 1 findPos tail list elt 但是如果列表中元素重复怎么办
  • ghci 中严格求和/严格折叠导致内存爆炸

    正如中提到的为什么 sum takeWhile 以下是not炸毁记忆ghci https stackoverflow com questions 14298930 why does sum takewhile 10000000 1 use
  • Haskell 类型族中的类型歧义

    我正在尝试整理以下课程Domain及其实例TrivialDomain LANGUAGE TypeFamilies data Transition Transition class Domain d where type Set d type
  • 如何构图“也许”镜头?

    如果我有嵌套记录的镜头 其中每个镜头返回一个Maybe 我怎样才能让它们组合起来 这样如果 遍历 中有任何东西返回一个Nothing最终结果是Nothing data Client Client clientProperties Maybe
  • 列出树中叶子的路径

    我正在尝试编写一个函数来查找树中叶子的所有路径 例如 给定一棵如下所示的树 1 2 5 3 4 6 输出列表将是 1 2 3 1 2 4 1 5 6 该函数的类型签名是 branches Tree a gt a 请注意 这使用了中定义的 T

随机推荐