Haskell:从 ghci 提示符中将表达式读取为整数?

Haskell: Reading expressions as Integers from ghci prompt?

我正在试验一些数论函数,并处理大整数。但是,我希望能够从提示中读取表达式。我有一个由

定义的函数
factor :: Integer -> Integer

如果我输入

ghci> factor 2047

它工作正常。但是我进不去

ghci> factor 2^11-1

因为表达式 2^11-1 未被计算(在提示符下)为 Integer。我可以用

解决这个问题
ghci> factor (toInteger 2^11-1)

但我想知道是否有一种方法可以自动将表达式读取为 Integer 值?

这与需要表达式“评估为 Integer 值”无关。 Haskell 在需要时计算任何表达式,并根据环境要求计算任何类型。

只是,factor 2^11-1解析(factor 2)^11 - 1,这显然不是你想要的。 (那里不存在子表达式 2^11-1!)但是 factor (2^11 - 1) 或 – 更喜欢的风格 – factor $ 2^11 - 1 会工作得很好。

事实上,factor (toInteger 2^11-1) 也不是您所想的那样:它被解析为 factor ((toInteger 2)^11 - 1)。完全没有必要写 toInteger 2,而只是 2.

Haskell 解析规则的简要概述:

  • 前缀函数应用总是优先的。因此 f x^y 被解析为 (f x)^y,而不是 f (x^y)
    • 这从左到右贪婪地工作。因此,f x y 被解析为 (f x) y,而不是 f (x y).
  • 中缀运算符根据其 固定性 进行解析,例如您可以使用 :i ^ 在 GHCi 中查找。例如,infixr 8 ^ 高于 infixl 6 -,这就是为什么 2^11-1 被解析为 (2^11) - 1 而不是 2 ^ (11-1)
    • 固定性中的lr 表示如果您链接同一运算符的多个实例时的方向。例如,infixr 5 : 表示 1:2:3:[] 被解析为 1:(2:(3:[])),而不是 ((1:2):3):[].

实际上这并不总是正确的。像 2 这样的文字是多态的,即它们真的可以被评估为你要求的任何类型。例如,2 * 3 + 4 * sin 5 :: Double 将执行所有操作作为 floating-point 乘法/加法。而 toInteger 实际上受到限制,因此结果必须始终是整数(如果您尝试在需要 Double 的设置中使用它,这实际上将是 compile-time 错误! ), 即它实际上等同于 (2 :: Integer).

虽然这在很多方面表现得更像其他语言写的 f(x,y)。这在 Haskell 中也是合法的,如果有点单调的话。 (那么 f 实际上不是两个参数的函数,而是一个恰好是元组的单个参数的函数。)