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)
。
- 固定性中的
l
或r
表示如果您链接同一运算符的多个实例时的方向。例如,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
实际上不是两个参数的函数,而是一个恰好是元组的单个参数的函数。)
我正在试验一些数论函数,并处理大整数。但是,我希望能够从提示中读取表达式。我有一个由
定义的函数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)
。- 固定性中的
l
或r
表示如果您链接同一运算符的多个实例时的方向。例如,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
实际上不是两个参数的函数,而是一个恰好是元组的单个参数的函数。)