4
votes

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

3
liOfLi is not a data constructor. It is a variable.dave4420
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 youtube.com/watch?v=2TS-W5woDcw ;-)epsilonhalbe

3 Answers

7
votes

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.

2
votes

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
1
votes

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).