【问题标题】:Strange behaviour in GHCiGHCi 中的奇怪行为
【发布时间】:2015-03-23 06:36:24
【问题描述】:

我写了以下代码:

it :: Int -> Int
it n
    | n < 1     = error "Invalid entry."
    | n == 1    = 0
    | otherwise = 1 + it (n `quot` 2)

当我将它加载到 GHCi 中时,发生了一些奇怪的事情。我第一次调用函数it,它工作正常并返回预期结果。但是,下一次,我得到以下崩溃:

λ: :t it
it :: Int -> Int
λ: it 2
1
λ: it 2

<interactive>:4:1:
    Couldn't match expected type `a0 -> t0' with actual type `Int'
    The function `it' is applied to one argument,
    but its type `Int' has none
    In the expression: it 2
    In an equation for `it': it = it 2
λ: :t it
it :: Int
λ: it
1

似乎it 的类型在第一次调用后被某种方式修改了。当从main 多次调用it 时,事情变得更加奇怪,即所有调用都返回预期结果,但最终() 被分配为it 的类型:

main :: IO ()
main = do
    let r1 = it 1
        r2 = it 2
        r3 = it 3
    print r1
    print r2
    print r3

λ: main
0
1
1
λ: :t it
it :: ()

我相信这是与标识符 it 和 GHCi 内部相关的错误,因为将函数重命名为其他名称(如 it')完全解决了这个问题。除此之外,函数的主体似乎没有影响;做let it = (+) 2 并多次评估它也是有问题的。

任何见解将不胜感激。 ghci --version 的输出是“版本 7.6.3”。

【问题讨论】:

    标签: haskell ghci


    【解决方案1】:

    命名不顺:it是GHCi自动绑定到你之前评估结果的名字,方便你再次参考。因此,您的第一次使用会立即重新绑定它,从而影响您的定义。

    如果it 被定义在一个模块中,你应该仍然能够从 GHCi 中使用模块前缀可靠地引用它,例如Main.it.

    【讨论】:

    • 感谢您的回答!我很高兴知道这只是“错误与功能”困境的另一个例子。 :-) 我当然看到it 的用处,但我想知道是否有更好的方法可以在 GHCi 中实现此功能以避免这种混淆......也许使用特殊关键字,而不是有效的 Haskell 函数标识符?或者至少在加载使用保留 GHCi 名称命名的函数时警告用户......最后,我应该注意 GHCi 中的任何其他特殊名称吗?
    • @alexandrelucchesi 我记得很久以前,Hugs 使用了$$,尽管这可能与运算符混淆。我认为 GHCi 使用普通标识符,因为该功能是作为普通代码实现的,请参阅the manual。其他特殊名称我不知道,:show bindings 不再列出。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-06
    • 2012-09-01
    相关资源
    最近更新 更多