[GHC] #10160: GHCi :sprint has odd/unhelpful behavior for values defined within the REPL

GHC ghc-devs at haskell.org
Thu Mar 19 04:41:38 UTC 2015


#10160: GHCi :sprint has odd/unhelpful behavior for values defined within the REPL
-------------------------------------+-------------------------------------
        Reporter:  bitemyapp         |                   Owner:
            Type:  bug               |                  Status:  new
        Priority:  normal            |               Milestone:
       Component:  GHCi              |                 Version:  7.8.4
      Resolution:                    |                Keywords:  :sprint
Operating System:  Unknown/Multiple  |  thunk evaluation non-strictness
 Type of failure:  Incorrect result  |  laziness runtime ghci repl
  at runtime                         |            Architecture:
      Blocked By:                    |  Unknown/Multiple
 Related Tickets:                    |               Test Case:
                                     |                Blocking:
                                     |  Differential Revisions:
-------------------------------------+-------------------------------------
Description changed by bitemyapp:

Old description:

> Wanted to use :sprint to help learners visualise thunk evaluation
> behavior in their data. Ran into some behaviors that a few people I
> checked with didn't have a good explanation for. I couldn't find anything
> in the user guide to explain this. I don't think it technically violates
> Haskell Report requirements, but it makes :sprint considerably less
> useful if you're teaching somebody non-strictness.
>
> Examples with code in the REPL:
>
> {{{
> Prelude> let x = [1, 2, 3 :: Integer]
> Prelude> :sprint x
> x = [1,2,3]
> -- errr, what?
>
> Prelude> let x = Just (1 :: Integer)
> Prelude> :sprint x
> x = Just 1
>
> Prelude> let just = Just
> Prelude> let x = just (1 :: Integer)
> Prelude> :sprint x
> x = _
>
> Prelude> let x = Just (undefined :: Integer)
> Prelude> :sprint x
> x = Just _
>
> Prelude> let x = just (undefined :: Integer)
> Prelude> :sprint x
> x = _
>
> Prelude> let x = [1, 2, 3 :: Integer]
> Prelude> let y = x
> Prelude> :sprint y
> y = [1,2,3]
>
> Prelude> let x = 1 : 2 : (3 :: Integer) : []
> Prelude> :sprint x
> x = [1,2,3]
> Prelude> let x = [1] ++ [2] ++ [(3 :: Integer)]
> Prelude> :sprint x
> x = _
>
> Prelude> let y = (:)
> Prelude> let x = 1 `y` (2 `y` ((3 :: Integer) `y` []))
> Prelude> :sprint x
> x = _
> Prelude> x
> [1,2,3]
> Prelude> :sprint x
> x = [1,2,3]
> }}}
>
> So the behavior here seems to be:
>
> Constructors used directly in the construction of data and are not passed
> functions (including polymorphic vals awaiting concrete
> instances)/bottoms are immediately evaluated
>
> Example, but with loading data from a file:
>
> Contents of the file:
>
> {{{
> x :: Num a => [a]
> x = [1, 2, 3]
> }}}
>
> GHCi session:
>
> {{{
> Prelude> :t x
> x :: Num a => [a]
>
> Prelude> :sprint x
> x = _
>
> Prelude> x
> [1,2,3]
>
> Prelude> :sprint x
> x = _
> }}}
>
> Then when x is loaded from a file, but has a different type:
>
> {{{
> Prelude> :t x
> x :: [Integer]
> Prelude> :sprint x
> x = _
> Prelude> head x
> 1
> Prelude> :sprint x
> x = [1,2,3]
> }}}
>
> Now, this is a bit confusing. Earlier I was able to get :sprint to return
> [1, _, _] when I evaluated head x, but a couple hours later when I went
> to write this ticket, I couldn't reproduce that behavior.
>
> Is there documentation that explains:
>
> 1. Why data is shown as having been evaluated at time of declaration
> (seemingly) by :sprint when it's defined in the GHCi
>
> 2. Why declaring code in GHCi and loading it from a file behaves
> differently with :sprint (I considered let expression in the implicit
> GHCi do-block...couldn't find anything to explain this)
>
> 3. Why evaluating 'head x' forces the other values as well
>
> Are any of these behaviors a bug? If not, are they documented anywhere?
> Is the "eager" treatment of constructors in GHCi a performance thing?
> That seems strange given I didn't have -fobject-code turned on.
>
> :sprint not demonstrating semantics that match what I expect from a non-
> strict language hinders its utility as a teaching tool and means the only
> robust option for learners that I can find is testing evaluation with
> bottom values.
>
> {{{
> -- So that you know i picked "7.8.4" as the version consciously
>
> [callen at atlantis ~/Work/fpbook]$ ghc --version
> The Glorious Glasgow Haskell Compilation System, version 7.8.4
>
> [callen at atlantis ~/Work/fpbook]$ ghci --version
> The Glorious Glasgow Haskell Compilation System, version 7.8.4
> }}}

New description:

 Wanted to use :sprint to help learners visualise thunk evaluation behavior
 in their data. Ran into some behaviors that a few people I checked with
 didn't have a good explanation for. I couldn't find anything in the user
 guide to explain this. I don't think it technically violates Haskell
 Report requirements, but it makes :sprint considerably less useful if
 you're teaching somebody non-strictness.

 Examples with code in the REPL:

 {{{
 Prelude> let x = [1, 2, 3 :: Integer]
 Prelude> :sprint x
 x = [1,2,3]
 -- errr, what?

 Prelude> let x = Just (1 :: Integer)
 Prelude> :sprint x
 x = Just 1

 Prelude> let just = Just
 Prelude> let x = just (1 :: Integer)
 Prelude> :sprint x
 x = _

 Prelude> let x = Just (undefined :: Integer)
 Prelude> :sprint x
 x = Just _

 Prelude> let x = just (undefined :: Integer)
 Prelude> :sprint x
 x = _

 Prelude> let x = [1, 2, 3 :: Integer]
 Prelude> let y = x
 Prelude> :sprint y
 y = [1,2,3]

 Prelude> let x = 1 : 2 : (3 :: Integer) : []
 Prelude> :sprint x
 x = [1,2,3]
 Prelude> let x = [1] ++ [2] ++ [(3 :: Integer)]
 Prelude> :sprint x
 x = _

 Prelude> let y = (:)
 Prelude> let x = 1 `y` (2 `y` ((3 :: Integer) `y` []))
 Prelude> :sprint x
 x = _
 Prelude> x
 [1,2,3]
 Prelude> :sprint x
 x = [1,2,3]
 }}}

 So the behavior here seems to be:

 Constructors used directly in the construction of data and are not passed
 functions (including polymorphic vals awaiting concrete instances)/bottoms
 are immediately evaluated

 Example, but with loading data from a file:

 Contents of the file:

 {{{
 x :: Num a => [a]
 x = [1, 2, 3]
 }}}

 GHCi session:

 {{{
 Prelude> :t x
 x :: Num a => [a]

 Prelude> :sprint x
 x = _

 Prelude> x
 [1,2,3]

 Prelude> :sprint x
 x = _
 -- ^^ this is expected
 }}}

 Then when x is loaded from a file, but has a different type:

 {{{
 Prelude> :t x
 x :: [Integer]
 Prelude> :sprint x
 x = _
 Prelude> head x
 1
 Prelude> :sprint x
 x = [1,2,3]
 -- ^^ this is not
 }}}

 Now, this is a bit confusing. Earlier I was able to get :sprint to return
 [1, _, _] when I evaluated head x, but a couple hours later when I went to
 write this ticket, I couldn't reproduce that behavior.

 Is there documentation that explains:

 1. Why data is shown as having been evaluated at time of declaration
 (seemingly) by :sprint when it's defined in the GHCi

 2. Why declaring code in GHCi and loading it from a file behaves
 differently with :sprint (I considered let expression in the implicit GHCi
 do-block...couldn't find anything to explain this)

 3. Why evaluating 'head x' forces the other values as well

 Are any of these behaviors a bug? If not, are they documented anywhere? Is
 the "eager" treatment of constructors in GHCi a performance thing? That
 seems strange given I didn't have -fobject-code turned on.

 :sprint not demonstrating semantics that match what I expect from a non-
 strict language hinders its utility as a teaching tool and means the only
 robust option for learners that I can find is testing evaluation with
 bottom values.

 {{{
 -- So that you know i picked "7.8.4" as the version consciously

 [callen at atlantis ~/Work/fpbook]$ ghc --version
 The Glorious Glasgow Haskell Compilation System, version 7.8.4

 [callen at atlantis ~/Work/fpbook]$ ghci --version
 The Glorious Glasgow Haskell Compilation System, version 7.8.4
 }}}

--

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/10160#comment:3>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list