
#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 Keywords: :sprint | Operating System: Unknown/Multiple thunk evaluation | Type of failure: Incorrect result Architecture: | at runtime Unknown/Multiple | Blocked By: Test Case: | Related Tickets: Blocking: | Differential Revisions: | -------------------------------------+------------------------------------- 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] Prelude> :sprint x x = _ Prelude> :t x x :: Num t => [t] -- this makes sense so far. 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@atlantis ~/Work/fpbook]$ ghc --version The Glorious Glasgow Haskell Compilation System, version 7.8.4 [callen@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 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler