4

Why I am forced to write liOfLi in place of LiOfLi? Please guide.

code in baby.hs

LiOfLi = [ [1,3,4,5,6,8], [ 12, 13, 15, 16, 19, 20], [23, 24, 25, 45, 56] ]

ghci response:

ghci> :l baby
[1 of 1] Compiling Main ( baby.hs, interpreted )
Failed, modules loaded: none.

ghci> baby.hs:29:1: Not in scope: data constructor `LiOfLi'

When changing the initial letter to smaller case

code in baby.hs

liOfLi = [ [1,3,4,5,6,8], [ 12, 13, 15, 16, 19, 20], [23, 24, 25, 45, 56] ]

ghci response:

ghci> :l baby
[1 of 1] Compiling Main ( baby.hs, interpreted )
Ok, modules loaded: Main.

Following are the SO questions I referred but I failed to understand the rules/ logic and get the answer for (my) abovementioned question.

Why does Haskell force data constructor's first letter to be upper case?

the variable names need to be lowercase. The official documentation related to this is at haskell.org/onlinereport/intro.html#namespaces – (the SO comment by) Chris Kuklewicz

Community
  • 1
  • 1
Optimight
  • 2,989
  • 6
  • 30
  • 48
  • 1
    `liOfLi` is not a data constructor. It is a variable. – dave4420 Jun 27 '12 at 02:58
  • in haskell you often go by making the the quasi plural by appending an 's' (or sometimes i use the same letter twice), i.e. if I got a list of integers `i`, one would write `is` or `ii` for a list of integers - I would then repeat the same `iss` or `iii`. There is usually another name that comes to use for a list of lists of numbers -- matrix. but `liOfLi` is hard to read and always reminds me of the german lullaby http://www.youtube.com/watch?v=2TS-W5woDcw ;-) – epsilonhalbe Jun 27 '12 at 07:22

3 Answers3

8

Data constructors (type constructors also) must begin with an uppercase letter. In your second example that actually compiles, liOfLi is not a data constructor, it's a variable (which begin with lower-case letters).

This:

liOfLi = [ [1,3,4,5,6,8], [ 12, 13, 15, 16, 19, 20], [23, 24, 25, 45, 56] ]

declares that a variable liOfLi is equal to [ [1,3,4,5,6,8], [ 12, 13, 15, 16, 19, 20], [23, 24, 25, 45, 56] ].

On the other hand, this:

LiOfLi = [ [1,3,4,5,6,8], [ 12, 13, 15, 16, 19, 20], [23, 24, 25, 45, 56] ]

is a pattern match of the pattern LiOfLi against the expression [ [1,3,4,5,6,8], [ 12, 13, 15, 16, 19, 20], [23, 24, 25, 45, 56] ]. As a pattern match it's fairly useless, because it contains no variables so even if it worked it wouldn't do anything. It fails to compile LiOfLi as a pattern is looking for all expressions matching the constructor LiOfLi applied to 0 arguments; since the constructor LiOfLi isn't defined anywhere your program can't be compiled.

The only way you could make LiOfLi be a 0-argument constructor is to introduce a new type, like so:

data MyNewType = LiOfLi

But LiOfLi = [ [1,3,4,5,6,8], [ 12, 13, 15, 16, 19, 20], [23, 24, 25, 45, 56] ] still wouldn't work, because it's trying to match the pattern LiOfLi, which is a pattern for values of type MyNewType, against the value [ [1,3,4,5,6,8], [ 12, 13, 15, 16, 19, 20], [23, 24, 25, 45, 56] ], which is a value of the list type.

Basically that equation means two different things depending on whether the term on the left of the = is interpreted as a pattern or as a variable. Haskell's designers chose to make it always easy to tell (for both human readers and the compiler) whether a given identifier is a constructor or a variable by the case of its first letter, which in turn allows you tell whether an equation is a pattern binding or a variable definition.

Ben
  • 68,572
  • 20
  • 126
  • 174
2

When you write

liOfLi = [ [1,3,4,5,6,8], [ 12, 13, 15, 16, 19, 20], [23, 24, 25, 45, 56] ]

you define the variable liOfLi to yield the value given by the list of lists. In contrast, a Data Constructor is used to define an algebraic data type, for example, you could define the following data type:

data Tree a = Nil | Node a (Tree a) (Tree a) 

Here, Nil and Node are both data constructors for type Tree a. You can look at their types in ghci, which will show:

Node :: a -> Tree a -> Tree a -> Tree a
Nil  :: Tree a
Peter
  • 1,693
  • 13
  • 18
  • `liOfLi` isn't a function, it's a variable with type `[Integer]`. If it were a function, it would be a variable with a type of the form `α -> β`. (See ["'Everything is a function' in Haskell?"](http://conal.net/blog/posts/everything-is-a-function-in-haskell) for a discussion of why everything is *not* a function.) – Antal Spector-Zabusky Jun 27 '12 at 03:22
  • Ok, although I somewhat disagree with calling it a "variable", as its value is fixed. – Peter Jun 27 '12 at 04:30
  • See the question ["Does Haskell Have Variables?"](http://stackoverflow.com/questions/993124/does-haskell-have-variables) for a discussion of that exact question :-) The stance I take is that it's a variable in the math sense, as well as the term used in the Haskell Report. – Antal Spector-Zabusky Jun 27 '12 at 04:51
1

A "data constructor" in Haskell is connected to a custom type. It gives data a certain context, it isn't actually the data. Types and data constructors must be uppercase.

Lowercase indicates a name for a function or a variable. When you use that lowercase name in your example, it could be replaced by the list on the right side.

In this case, the data constructor is [] (actually shorthand for something else).

Antal Spector-Zabusky
  • 36,191
  • 7
  • 77
  • 140
Enra
  • 86
  • 1
  • 4
  • `liOfLi` isn't a function, it's a variable with type `[Integer]`. If it were a function, it would be a variable with a type of the form `α -> β`. (See ["'Everything is a function' in Haskell?"](http://conal.net/blog/posts/everything-is-a-function-in-haskell) for a discussion of why everything is *not* a function.) Similarly, data constructors aren't types, they are values. `Maybe` has two constructors, `Just` and `Nothing`. – Antal Spector-Zabusky Jun 27 '12 at 03:28
  • In this case I would fall under the category of keeping things simple. It seemed like the asker had the wrong idea, thus trying to make it clear that capital letters are type-related, and lowercase indicates that you can replace the left side of the equal-sign with the right side (this is my mnemonic from math for functions.) But I'll edit to be more precise. – Enra Jun 27 '12 at 03:44
  • Definitely laudable motivation! It's just that I've seen a number of people get confused by the difference between data types and data constructors; for instance, saying things like "so this has type cons here". – Antal Spector-Zabusky Jun 27 '12 at 04:06