Why :sprint always prints a “_”?

前端 未结 3 2049
小鲜肉
小鲜肉 2020-11-30 12:31
Prelude> let a = 3
Prelude> :sprint a
a = _
Prelude> let c = \"ab\"
Prelude> :sprint c
c = _

Why does it always print a _?

相关标签:
3条回答
  • 2020-11-30 12:57

    I'm a bit late, but I had a similar issue:

    λ: let xs = [1,2,3]
    xs :: Num t => [t]
    λ: :sprint xs
    xs = _
    λ: print xs
    λ: :sprint xs
    xs = _
    

    This issue is specific to polymorphic values. If you have -XNoMonomorphismRestriction enabled ghci will never really evaluate/force xs, it'll only evaluate/force specializations:

    λ: :set -XMonomorphismRestriction
    λ: let xs = [1,2,3]
    xs :: [Integer]
    λ: print xs
    λ: :sprint xs
    xs = [1,2,3]
    
    0 讨论(0)
  • 2020-11-30 12:57

    Haskell is lazy. It doesn't evaluate things until they are needed.

    The GHCi sprint command (not part of Haskell, just a debugging command of the interpreter) prints the value of an expression without forcing evaluation.

    When you write

    let a = 3
    

    you bind a new name a to the right-hand side expression, but Haskell won't evaluate that thing yet. Therefore, when you sprint it, it prints _ as the value to indicate that the expression has not yet been evaluated.

    Try this:

    let a = 3
    :sprint a -- a has not been evaluated yet
    print a -- forces evaluation of a
    :sprint a -- now a has been evaluated
    
    0 讨论(0)
  • 2020-11-30 12:59

    Haskell is a lazy language. It doesn't evaluate results until they are "needed".

    Now, just printing a value causes all of it to be "needed". In other words, if you type an expression in GHCi, it will try to print out the result, which causes it all to be evaluated. Usually that's what you want.

    The sprint command (which is a GHCi feature, not part of the Haskell language) allows you to see how much of a value has been evaluated at this point.

    For example:

    Prelude> let xs = [1..]
    Prelude> :sprint xs
    xs = _
    

    So, we just declared xs, and it's currently unevaluated. Now let's print out the first element:

    Prelude> head xs
    1
    Prelude> :sprint xs
    xs = 1 : _
    

    Now GHCi has evaluated the head of the list, but nothing more.

    Prelude> take 10 xs
    [1,2,3,4,5,6,7,8,9,10]
    Prelude> :sprint xs
    xs = 1 : 2 : 3 : 4 : 5 : 6 : 7 : 8 : 9 : 10 : _
    

    Now the first 10 elements are evaluated, but more remain. (Since xs is an infinite list, that's not surprising.)

    You can construct other expressions and evaluate them a bit at a time to see what's going on. This is really part of the GHCi debugger, which lets you step through your code one bit at a time. Especially if your code is getting caught in an infinite loop, you don't want to print anything, because that might lock up GHCi. But you still want to see what's going on... hence sprint, which lets you see what's evaluated so far.

    0 讨论(0)
提交回复
热议问题