Give an ugly example:
data Bighead = Big little = 1 f1 = little :: Int f2 = Big :: BigHead
In my opinion:
f1
and f2
all point to some data. the only different of (little
and Big
) is little has a piece of code to do evaluation. but Big doesn't.
They all have a rewritable body, little can be transformed from a collection of data to a result, and Big is just don't do the last step --- it always holds this data forms (but recursively they can be evaluated).
But in syntax form, they are almost the same: can be applied, can be evaluated.
One big deal may be that functions can't alter its applied params, but data can do.
Is this the only reason that Haskell treats data and function's names differently?
Call for analysis :-)
edit: some more pads
data A = B Int
type of B
:
B :: Int -> A b :: Int -> A b = B
Haskell is a case-sensitive programming language because functions must begin with capital letters. By contrast, types must start with an upper case letter. However, it is essential to note that in Haskell, the capitalization of the identifier usually encodes information about semantics.
() is very often used as the result of something that has no interesting result. For example, an IO action that is supposed to perform some I/O and terminate without producing a result will typically have type IO () .
Haskell has three basic ways to declare a new type: The data declaration, which defines new data types. The type declaration for type synonyms, that is, alternative names for existing types. The newtype declaration, which defines new data types equivalent to existing ones.
You need to use map (map toUpper) . This is because you have [String] instead of String . i.e. map toUpper capitalises a String, by making each letter uppercase, so map (map toUpper) capitalises each String in a list of Strings.
From the Haskell 98 Language we see the core distinction in identifier tokens in Haskell:
varid -> (small {small | large | digit | ' })<reservedid> conid -> large {small | large | digit | ' }
That is, the language fundamentally distinguish variable names ("varid") from constructor names ("conid"), at all levels of the language (both value and type variables and constructors). So clearly, Haskell distinguishes identifiers into two main namespaces (well, there are others, if you count modules and classes), but two primary ones, those that begin with a lower-case letter (variable identifiers) and those that begin with an upper-case letter (constructor identifiers).
So, given that we do distinguish constructors from variables, the question is "why?".
Reading types
One plausible argument is that it makes it very easy to spot parameters in types (e.g. polymorphic types).
Pattern matching
Secondly, and more importantly, we have uniform syntax for data construction and deconstruction (pattern matching). Whenever you see an upper case identifier in a pattern,
case x of Foo y z -> ...
You know that Foo
is a data structure being taken apart and its components named. Correspondingly, whenever you see an upper case identifier in an expression,
g (f (Foo 1 2)
you know that f
is receiving a newly built Foo
data type with two arguments.
So, since constructors (both type and value) are so important in the language, this simple restriction to upper case identifiers makes it much easier for a human to see what is going on in a piece of code. In some ways upper case letters make up for the lack of other syntactic noise in the language, as an aid to the reader.
Namespaces
There are six kinds of names in Haskell : those for variables and constructors denote values; those for type variables, type constructors, and type classes refer to entities related to the type system; and module names refer to modules. There are two constraints on naming:
Names for variables and type variables are identifiers beginning with lowercase letters or underscore; the other four kinds of names are identifiers beginning with uppercase letters. An identifier must not be used as the name of a type constructor and a class in the same scope. These are the only constraints; for example, Int may simultaneously be the name of a module, class, and constructor within a single scope.
Haskell B
In Haskell B, constructors and variables could use either case.
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