Haskell 中美元符号 ($) 和 id 函数之间有关系吗?

2024-05-07

这几天我正在读一篇评论莫纳德挑战 http://mightybyte.github.io/monad-challenges/(我强烈推荐给像我这样的 Haskell 初学者),我最终得到了这个线程 https://news.ycombinator.com/item?id=10935313我在哪里读到的($) = id.

我不知道这会吓到人们,但许多编程语言都有一些概念,这些概念最好通过小例子来展示,让人们说“哇”。

例如,令人惊奇的是,Prolog 中的append() 可以从连接的结果“向后”运行,以生成可以连接以生成它的所有列表。或者 Haskell 中的一元绑定运算符 (>>=) 可以根据 join 和 fmap 定义,或者 ($) = id。

($) = id !?

我现在明白为什么这是真的了,但仍然......哇啊!!感谢那! (...)

然后我检查了base-4.10.0.0 https://hackage.haskell.org/package/base-4.10.0.0/docs/src/GHC.Base.html代码,寻找定义($) and id,但在顶部我读到了这个:


NOTA BENE: Do NOT use ($) anywhere in this module! The type of ($) is
slightly magical (it can return unlifted types), and it is wired in.
But, it is also *defined* in this module, with a non-magical type.
GHC gets terribly confused (and *hangs*) if you try to use ($) in this
module, because it has different types in different scenarios.

This is not a problem in general, because the type ($), being wired in, is not
written out to the interface file, so importing files don't get confused.
The problem is only if ($) is used here. So don't!  

他们的实现是:

-- | Identity function.
id                      :: a -> a
id x                    =  x

-- | Application operator.
{-# INLINE ($) #-}
($)                     :: (a -> b) -> a -> b
f $ x                   =  f x

我尝试在 GHCi 上交换一个,但得到的只是类型错误(正如我预期的那样)。现在,我有比一开始更多的问题:

  1. 他们这么说是什么意思($) = id?
  2. 在哪些情况下该陈述是正确的?这是否意味着我可以使用其中之一来代替另一个?
  3. In the base,这句话是什么意思($)是“有点神奇(它可以返回未提升的类型)”和“被连接”?
  4. 那么“不同场景不同类型”呢?我认为,由于 Haskell 是一种强类型语言,一旦定义了类型签名,该签名就会保留到时间结束。这不是真的吗?是否存在可以更改函数类型的情况?

Haskell 确实是强类型的;该问题与特定于某些黑客行为有关($)操作员。不幸的是,我不知道它是关于什么的:希望有人会自动回答你的问题 3(和问题 4)。

关于问题1,看一下类型:

id :: a -> a
($) :: (a -> b) -> (a -> b)

Rename c = a -> b你得到($) :: c -> c,这意味着类型($)是类型的规范id,这样至少类型允许我们使用id实施($).

现在,看看定义($):

f $ x = f x

让我们重写一下:

($) f = \x -> f x

并应用 eta 缩减:

($) f = f

现在可以清楚地看到($)只是id具有更具体的类型(这样f始终是一个函数)。

请注意,它不能以其他方式工作,因为($)更具限制性。例如,您可以调用id 5并得到5结果,但是($) 5不会进行类型检查:5没有表单的类型a -> b.

要点是($)是它的优先级非常低,并且允许避免在参数周围使用大括号f,并且可以像这样使用

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

Haskell 中美元符号 ($) 和 id 函数之间有关系吗? 的相关文章

  • 如何在 Yesod 中使用 CSS 框架?

    我想将 Blueprint CSS 框架与 Yesod 一起使用 有没有最佳实践 因为 Yesod 使用 CSS 模板 所以在我看来我不能直接使用 css 文件 我必须将它们重命名为 lucius files 吗 如何将 CSS 添加到 d
  • 类 GADT 类型变量的未来角色?

    A 昨天的问题 https stackoverflow com q 41135212 3072788有一个定义HList 来自HList https hackage haskell org package HList 0 4 1 0 doc
  • 如何为强制长度为 2^n 的向量类型定义可用的 Applicative 实例

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

    作为一个让我熟悉 Haskell 的简单练习 在 Youtube 上闲逛并偶然进入美国倒计时游戏节目之后 我想为数字游戏制作一个求解器 你得到 6 个数字 需要将它们与 为了得到给定的结果 到目前为止我所得到的是非常脑死亡的 let ope
  • 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 函数 head filter fst 现在的问题是如何手动 手动 找到类型 如果我让 Haskell 告诉我我得到的类型 head filter fst Bool b gt Bool b 但我想了解仅使用所用函数的签名
  • 将 num 的签名键入 double?

    我才刚刚开始为你学习 Haskell 以获得伟大的好处 并且我在类型类方面遇到了一些麻烦 我想创建一个接受任何数字类型并强制其为双精度的函数 我的第一个想法是定义 numToDouble Num gt Double 但我认为这不起作用 因为
  • Haskell - 用防护罩替换外壳

    我想知道在这部分代码中是否可以用守卫替换 case 语句 firstFunction String gt Maybe MyType secondFunction MyType gt Integer myFunction String gt
  • “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 空间 我可以采取同样的方式并
  • Haskell 中列表列表的笛卡尔积

    给定一个长度列表的列表x所有子列表的长度都相同y 输出y x长度列表x包含每个子列表中的一项 例子 x 3 y 2 1 2 3 4 5 6 Output 2 3 8不同的输出 1 3 5 1 4 5 1 3 6 1 4 6 2 3 5 2
  • Haskell 入门

    这个问题的答案是社区努力 help privileges edit community wiki 编辑现有答案以改进这篇文章 目前不接受新的答案或互动 几天来 我一直试图理解 Haskell 中的函数式编程范例 我通过阅读教程和观看截屏视频
  • 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 IRC 频道中有人问 是否有一种简洁的方法来定义一个列表 其中第 n 个条目是之前所有条目的平方和 我认为这听起来像一个有趣的谜题 递归定义无限列表是我真正需要练习的事情之一 所以我启动了 GHCi 并开始尝试递归定义
  • Haskell - lambda 表达式

    我试图了解什么是有用的以及如何在 Haskell 中实际使用 lambda 表达式 我不太明白使用 lambda 表达式相对于定义函数的约定方式有何优势 例如 我通常会执行以下操作 let add x y x y 我可以简单地打电话 add
  • 我该如何实现这个折叠功能呢?

    给出了两种数据类型 颜色 和 植物 data Color Red Pink White Blue Purple Green Yellow deriving Show Eq data Plant Leaf Blossom Color Stal
  • Haskell 标准库是什么?

    GHC专用库可以称为标准库吗 或者只有 Haskell 2010 报告中的那些才算数 许多 GHC 库可以通过 Haskell 报告中的函数来实现 可能与 C 绑定相结合 但其他语言依赖于 GHC 特定的扩展 因为语言报告中定义的当前 Ha
  • 如何在不声明新数据的情况下更改类型(String,Int)元组的 Ord 实例?

    我正在尝试对类型列表进行排序 String Int 默认情况下 它按字符串排序 然后按整数排序 如果字符串相等 我希望它是相反的 首先比较整数 然后如果相等则比较字符串 另外 我不想切换到 Int String 我找到了一种通过定义实例来实
  • 管道:多个流消费者

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

    我试图证明类型级函数Union https hackage haskell org package type level sets 0 8 5 0 docs Data Type Set html t Union是关联的 但我不确定应该如何完

随机推荐