我正在尝试一些数论函数,并处理大整数。但是,我希望能够从提示中读取表达式。我有一个由
定义的函数factor :: Integer -> Integer
如果我输入
ghci> factor 2047
它工作正常。但我无法进入
ghci> factor 2^11-1
因为表达式2^11-1
未在Integer
评估(在提示时)。我可以用
ghci> factor (toInteger 2^11-1)
但我想知道是否有办法自动将表达式读作Integer
个值?
答案 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)
。:i ^
在GHCi中查找。例如,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
实际上不是两个参数的函数,而是一个恰好是元组的单个参数的函数。)