我正在尝试一些数论函数,并处理大整数.但是,我希望能够从提示符中读取表达式.我有一个定义的函数
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)
.
中缀运算符根据其固定性进行解析,例如,您可以在GHCi中查找:i ^
.例如,infixr 8 ^
高于infixl 6 -
,这2^11-1
就是解析为(2^11) - 1
和不解析的原因2 ^ (11-1)
.
的l
或r
在固定性表示如果链中的相同运营商的多个实例的方向.例如,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
实际上不是两个参数的函数,而是一个恰好是元组的单个参数的函数.)