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
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With