I'm working through haskell book and I understood that :sprint x
is used to print the elements of x has been evaluated and the elements has been not(the ones which aren't are expressed by an '_').
One of the examples provided in the book,
Prelude> let blah = enumFromTo 'a' 'z'
Prelude> :sprint blah
blah = _
Prelude> take 1 blah
"a"
Prelude> :sprint blah
blah = 'a' : _
To test out with different input i did this in GHCi:-
prelude> let b = [1,2,3,4,5]
prelude> :sprint b
b = _
prelude> take 1 b
[1]
prelude> :sprint b
b = _
Shouldn't the output of :sprint b
in the last command be b = 1 : _
since we are only evaluating a single list item and a cons operator when using the command take 1 b
?? But it's showing the output above. How and why is this happening ? Shouldn't the output be similar to the output of String type?
Edit: I've been experimenting more and got this result :-
prelude> let b = [1..10] :: [Int]
prelude> :sprint b
b = _
prelude> take 3 b
[1,2,3]
prelude> :sprint b
b = 1 : 2 : 3 : _
Okay, my initial guess is, it's because of the way I'm constructing the two lists ? One is using ranges and the other by explicitly stating its elements (which in turns creates the list by using the cons ':' constructor recursively on its elements)
The behavior of :sprint
can be a little tricky. In this case, look at the type of x
:
> :t x
x :: Num t => [t]
Because it's polymorphic, the actual values that get produced depend on the specific instance of Num
that you require. Thus, x
behaves more like a function that will produce the list [1,2,3,4,5]
when it can figure out just what type you want the elements to have.
Now you might think, "ok, I'll make a list that isn't polymorphic", so you try this:
> let x = [1,2,3,4,5 :: Int]
> :t x
x :: [Int]
> :sprint x
x = [1,2,3,4,5]
What the heck? If you think about it, this makes sense. We've told ghci explicitly what the list is. It's not like it can unevaluate it and then reevaluate it later. (This would be wasteful anyway.) But let's see what happens when we try to map a function over x:
> let y = map (+1) x
> :sprint y
y = _
> take 1 y
[2]
> :sprint y
y = 2 : _
Just as expected!
Hope that helps. Lazy evaluation is one of the trickier things about Haskell (when it becomes important).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With