Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why I am forced to write the (Data Constructor) name with first letter in small case?

Tags:

haskell

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

like image 883
Optimight Avatar asked Dec 27 '22 22:12

Optimight


2 Answers

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.

like image 104
Ben Avatar answered Dec 29 '22 12:12

Ben


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
like image 25
Peter Avatar answered Dec 29 '22 13:12

Peter