Haskell:从ghci提示中读取表达式为Integers?

时间:2016-01-11 00:10:01

标签: haskell types numbers

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

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

如果我输入

ghci> factor 2047

它工作正常。但我无法进入

ghci> factor 2^11-1

因为表达式2^11-1未在Integer评估(在提示时)。我可以用

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

但我想知道是否有办法自动将表达式读作Integer个值?

1 个答案:

答案 0 :(得分:9)

这与需要表达式“评估为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)
  • 根据其 fixity 解析中缀运算符,您可以使用: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将执行所有操作作为浮点乘法/加法。事实上toInteger实际上是受限制的,因此结果必须始终为整数(如果您尝试在期望Double的设置中使用它,这实际上是编译时错误!),即它实际上等同于(2 :: Integer)

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