What is the evaluaton order in simple List creation? - haskell

How is 1:(2:(3:[])) evaluated?
What rewriting steps are taken until we arrive to [1,2,3] ?
Is it
1:(2:([3])
1:([2,3])
[1,2,3]
or something else? Is the above described way the only way? Or is there an other way?

There isn't anything for Haskell to actually evaluate here, since : is the constructor for lists. When you write something like [1, 2, 3], the compiler first de-sugars this to the form 1 : 2 : 3 : [], and this is its representation in memory. It'd be like asking what the evaluation order is for Just 1. There isn't an evaluation order, because it's already in its "most evaluated" form, also known as normal form.
For lists, normal form is elements consed together in front of an empty list. If it helps, you can think of lists defined as
data [a] = [] | a : [a]
Or alternatively
data List a = Empty | Cons a (List a)
When you do pattern matching like
f (x:xs) = ...
This is equivalent to doing pattern matching like
f (Cons x xs) = ...
The only real difference is the names used.
So I guess the answer to your question is that you have the evaluation backwards, you don't go from 1:2:3:[] to [1, 2, 3], you go from [1, 2, 3] to 1:2:3:[], although this step occurs during de-sugaring. As for list comprehensions, these get de-sugared into maps and filters using monadic functions like >> and >>=. When you see something like [1..10], this actually uses the Enum instance for its elements and gets de-sugared to fromEnumTo and similar functions. All of these functions work with lists on the level of : and [], so they're just working with the list type's constructors just as it would with any other data type.
As proof, if I had the code
module Foo where
x :: [Int]
x = [1, 2, 3]
And I compiled it with ghc -c Foo.hs -ddump-ds, I'd get
Foo.x :: [GHC.Types.Int]
[LclIdX]
Foo.x =
GHC.Types.:
# GHC.Types.Int
(GHC.Types.I# 1)
(GHC.Types.:
# GHC.Types.Int
(GHC.Types.I# 2)
(GHC.Types.:
# GHC.Types.Int (GHC.Types.I# 3) (GHC.Types.[] # GHC.Types.Int)))
Which is has quite a lot of extra meta-data in there, so let's remove all the extra type annotations, module names, and other noise:
Foo.x :: [Int]
Foo.x = GHC.Types.: 1 (GHC.Types.: 2 (GHC.Types.: 3 []))
Or even more removed
x :: [Int]
x = : 1 (: 2 (: 3 []))
Note that in core (what GHC compiles Haskell source to, one of the 3 intermediate language used), we don't need parens around operators in prefix form. But it's pretty easy to see that once everything is de-sugared it's simply represented as a list consed together.
But wait! I thought you said that the parens weren't needed? That was true when it was in infix form, but now the : is being applied as a prefix function. It's pretty easy to see that with prefix, the parens are needed, especially if you replace : with Cons and [] with Empty:
x = Cons 1 (Cons 2 (Cons 3 Empty))
Since the following wouldn't type-check. It makes it look like Cons takes 6 arguments!
x = Cons 1 Cons 2 Cons 3 Empty

Related

Syntax and semantics of symbol characters in Haskell

I'm learning Haskell.
One of my standard techniques when learning a new language is to implement a Hello World genetic algorithm that attempts to generate a string via genetic algorithm techniques that matches some input string.
Due to my inexperience with Haskell (the closest thing I have to compare is Kotlin) I searched for an example code so I could match my existing understanding of basic genetic algorithm to the code and intuit some understanding of Haskell based on my already underway reading/research on the language.
I came across this tutorial: https://www.arcadianvisions.com/blog/2011/haskell-genetic-algorithm-hello-world.html
I transcribed it in atom after setting my environment up, each part I didn't understand I did a quick google, if I didn't understand the syntax/semantics after 15 minutes I would carry on transcribing with the intent to catch up later on those particular parts.
So, I understood most of the code, such as the order of function application, monads (think I'm nearly there with monads anyway), data types, function types, currying, type substitution etc. However, there were several bits of syntax/semantics that I haven't seen in my reading/researching and not sure what they do, but they appear a lot in the code example I linked to above. I'm hoping someone can explain them to me:
(++)
(:)
<$>
<*>
(,)
(x !!)
p#(info#())
I am assuming the () and <> are some special syntax and the stuff inside them is semantic? When I hover over them in atom (I'm using atom-haskell-ghc) I can see the type Functor f => Applicative (f :: * -> *) where <*> :: f (a -> b) -> f a -> f b which kind of looks like a monad, but I don't really understand the weird syntax/semantics on the consuming end. Should I think of these as just another function (with a weird infix alias?).
Here is a specific line exhibiting several of the examples from above:
mate :: RandomGen g => Gene -> Gene -> Rand g Gene
mate gene1 gene2 = (++) <$> flip take gene1 <*> flip drop gene2 <$> pivot
where pivot = getRandomR (0, length gene1 - 1)
A note on operators
In Haskell you can define a function that has as identifier a sequence of symbols wrapped between brackets, like for example (++) or (:) that is an operator that can be used both as a function, like (++) x y, and as an infix operator, like x ++ y. Behind the curtains, the Haskell compiler will convert the infix operator to a function call, so x ++ y is completely equivalent with (++) x y (except for the fact that operators have different precedence rules).
(++)
This is the append function: (++) :: [a] -> [a] -> [a] it takes two lists as input, and constructs a list of the same type of elements that contains the elements of the first list followed by the elements of the second list. For example:
(++) [1, 4, 2, 5] [1, 3, 0, 2] == [1, 4, 2, 5, 1, 3, 0, 2]
(:)
This is a constructor of the list type [a]. It has type (:) :: a -> [a] -> [a]. It takes as input an element and a list of elements (all of the same type), it construct a list that starts with the first element, followed by the elements of the second parameter. For example:
(:) 1 [4, 2, 5] = [1, 4, 2, 5]
(<$>)
You wrote in your question <$>, but as you perhaps figured out, that means that somewhere a function (<$>) :: Functor f => (a -> b) -> f a -> f b is defined.
A Functor is a typeclass. Several types in Haskell are functors. The easiest ones are a list [], and a Maybe. The (<$>) takes as input a function f :: a -> b, and a functor instance, for example a list [a]. It will then convert it to a functor instance [b]. How this is done, depends on how the Functor instance is implemented (the (<$>) for a Maybe has different semantics than one for []).
Although the analogy is not complete, you can see a Functor sometimes as a collection of elements (a Maybe basically is a collection of zero Nothing, or one Just x elements). It will then map the elements the collection contains by channeling these through the function, for example:
(+1) <$> [1, 4, 2, 5] == [2, 5, 3, 6]
(+1) <$> Nothing == Nothing
(+1) <$> (Just 2) == Just 3
(<*>)
This function (<*>) :: Applicative f => f (a -> b) -> f a -> f b is again somewhat hard to understand. It makes use of an Applicative type class.
An type that is an instance of Applicative has to implement two functions: pure :: Applicative a => a -> f a and (<*>) :: Applicative f => f (a -> b) -> f a -> f b (or the programmer can decide to instead implement liftA2, but let us ignore that here).
Again you can see Applicative (at least for popular instances) as a collection (like [] or Maybe). Here we thus take as input such collection of functions (all with type a -> b), and a collection of as. We then "multiply" these, in the sense that for instance for a list:
[f1, f2, ..., fm] <*> [x1, x2, ..., xn]
== [f1 x1, f1 x2, ..., f1 xn,
f2 x1, f2 x2, ..., f2 xn,
...,
fm x1, fm x2, ..., fm xn]
So that means for instance for Maybe that if the left operand is Nothing, or the right operand is Nothing, or both are Nothing, then this results in a Nothing, if both are Justs (so Just f <*> Just x), then we obtain a Just (f x):
Just f <*> Just x == Just (f x)
Just f <*> Nothing == Nothing
Nothing <*> Just x == Nothing
Nothing <*> Nothing == Nothing
(,)
This is the constructor of a 2-tuple: (,) :: a -> b -> (a,b) thus takes as input an a and a b, and it constructs an 2-tuple where the first item is the first parameter, and the second item is the second parameter. For example:
(,) 4 'a' == (4, 'a')
(x !!)
This is a section of an infix operator. You can use an infix operator, and for instance specify the left or the right part. In that case you thus construct a partially applied function. For example:
([1, 4, 2, 5] !!) == (!!) [1, 4, 2, 5]
(!! 2) == flip (!!) 2
So for the latter it thus means that we constructed a function that takes as input a parameter that will be filled in as left operand. So:
(!! 2) [1, 4, 2, 5] == (!!) [1, 4, 2, 5]
The (!!) :: [a] -> Int -> a function takes as input a list and an Int and it returns the element at that index (zero-based indices).
p#(info#())
In contrast to the above, the # is not a function or operator (well these are actually the same), but a keyword.
It is used in pattern matching to obtain a reference to both an pattern and for instance match subpatterns (or obtain references to subpatterns).
For instance, say we want to pattern match a 2-tuple, and we want to have a reference to the entire tuple, and the first element, we can use:
somefunction total#(left, _) = ...
So if we then call somefunction (4, 'a'), then this means that total will hold (4, 'a'), and left will hold 4.
These are mostly all regular functions.
The <> are not special syntax, just part of the function name.
The () are regular parenthesis which group things and define precedence like in most other languages, the important note is that when you want to refer to an operator function (like ++) it must be in parenthesis.
++ is the list concatenation function [1,2] ++ [3,4] = [1,2,3,4], or without using infix notation (++) [1,2] [3,4] = [1,2,3,4]
: is the 'cons' function, it prepends an element to a list 1 : [2, 3, 4] = [1,2,3,4] or (:) 1 [2, 3, 4] = [1,2,3,4] without infix notation.
<$> is an infix operator alias of fmap
<*> is the applicative application function
, is the tuple constructor (,) 1 2 = (1, 2)
!! is the list index function [1,2,3] !! 1 = 2. Note that since these are singly linked lists, indexing is an O(n) operation.
# is used to define an "as pattern". When pattern matching it allows you to give a name to a parameter, while also destructuring it with pattern matching. For example the pattern f (xs#[x1, x2]) matches a two element list, where you can use x1 and x2 to refer to the individual elements and xs to refer to the list as a whole

Is literal a special form value constructor?

with
data ListType = List Int Int Int deriving(Show)
[1, 2, 3] and List 1 2 3, can both get a list which contains one to three, can I regard literal as a special form of value constructor?
Not just limits in Haskell.
can I regard literal as a special form of value constructor?
Basically, yes. Do note, however, that your ListType is not a list; it is (equivalent to) a tuple. Values of a list type may hold any number of elements, while ListType values can hold only three. Back to your question, though: [1, 2, 3] is indeed syntax sugar for 1 : 2 : 3 : [], in which the (:) and [] constructors appear explicitly. Weren't it for the sugar and other syntactical details, a definition for the list type might be:
data [] a = [] | (:) a ([] a)
I don't know what you mean by "literal", but the List data type that you defined above is actually not a conventional Haskell list. For one, your "List" has a fixed number of elements (3), while a Haskell list can contain from zero to an infinite number of elements. Your type is also specialized to the type Int, while Haskell lists can contain any type of elements, as long as all elements are of the same type. And, besides, Haskell lists are instances of a number of typeclasses (Functors, Monoids, Monads, etc.).
Haskell lists are a recursive data type and a possible constructor for them would be:
data List a = Empty | Cons a (List a) deriving Show
You could use this constructor as:
Cons 1 (Cons 2 (Cons 3 Empty))
Of course, it would be far more practical to use the built-in data type and build your list as:
[1,2,3]
Also, what do you really mean by "limits in Haskell"?
Haskell allows a custom syntax for lists, such as
[1,2,3]
this is just a syntactic shortcut for
1 : 2 : 3 : []
which is another syntactic shortcut for
(:) 1 ((:) 2 ((:) 3 []))
Above, (:) and [] are data constructors.
(:) :: a -> [a] -> [a]
[] :: [a]
Keep in mind that the special syntax applies only to standard lists, not to user defined types. You can get something vaguely similar with e.g.
data MyList a = Nil | a :+ MyList a
and then using the :+ value constructor in an infix way:
1 :+ 2 :+ 3 :+ Nil
Still, no [1,2,3] syntax for this type.

Haskell Matching pattern for lists

I'm very new to Haskell, and I decided to learn it some days ago, thanks to the haskell wikibook.
I'm reading at this moment the matching pattern for lists, but I can't understand the syntax for list.
Here's an example (from the wikibook) :
doubleList :: [Integer] -> [Integer]
doubleList [] = []
doubleList (n:ns) = (2 * n) : doubleList ns
I don't understand the part (n:ns). How should I read it ?
You can read it like this: (head:tail), so if you have [1, 2, 3] and you match it with (x:xs), then x will be bound to the first element in the list, 1, and xs will be bound to the rest of the list, in this case [2, 3].
(:) is an operator with type a->[a]->[a]. This means that it takes an item, and a list of those items, and returns another list of the same items. The output list is formed by prepending the input item to the input list.
Here is how you can use it
1:[2,3]
will return
[1,2,3]
Because the (:) appears on the left hand side of the definition, in your case, you are pattern matching, and the operator is being used to deconstruct the value, rather than build it.
For example, if we have
func (first:rest) = ....
and call it like this
func [1,2,3]
the following values would be assigned
first=1 --notice, this is type a
rest=[2,3] --notice, this is type [a]
Another tip that might help you understand is by looking at the definition of the list data type:
data [] a = [] | a : ([] a)
Note that Haskell makes special syntax rules just for the list type, normally [] is not a valid constructor. This definition is equivalent to
data List a = Empty | Cons a (List a)
Where
[] = Empty
(:) = Cons
You would pattern match on this as
doubleList :: List Int -> List Int
doubleList Empty = Empty
doubleList (Cons n ns) = Cons (2 * n) (doubleList ns)
If written using infix form:
doubleList (n `Cons` ns) = (2 * n) `Cons` doubleList ns
So now hopefully you can see the parallels between the two definitions. Haskell also provides the special syntax rule that
[1, 2, 3, 4] = 1:2:3:4:[]
Since the former is much easier to write and read. In fact, whenever you have a list literal like [1, 2, 3, 4] in your code, the compiler first converts it to 1:2:3:4:[] before converting your code into an executable.

Comparing List Elements in Haskell

I'm just learning Haskell and am kind of stuck.
I'd like to compare list elements and measure the difference between them and return the highest one.
Unfortunatly, I do not know how to approach that problem.
For usual, I'd just iterate the list and compare the neighbours but that does not seem to be the way to go in Haskell.
I already tried using map but as I said I do not really know how you can solve that problem.
I'd be thankful for every kind of advice!
Best wishes
Edit: My idea is to first zip all pairs like this pairs a = zip a (tail a). Then I'd like to get all differences (maybe with map?) and then just chose the highest one. I just can't handle the Haskell syntax.
I don't know what you mean by "measure the discrepancy" between list elements, but if you want to calculate the "largest" element in a list, you'd use the built-in maximum function:
maximum :: Ord a => [a] -> a
This function takes a list of values that can be ordered, so all numbers, chars, and strings, among others.
If you want to get the difference between the maximum value and the minimum value, you can use the similar function minimum, then just subtract the two. Sure, there might be a slightly faster solution whereby you only traverse the list once, or you could sort the list then take the first and last elements, but for most cases doing diff xs = maximum xs - minimum xs is plenty fast enough and makes the most sense to someone else.
So what you want to do is compute a difference between successive elements, not calculate the minimum and maximum of each element. You don't need to index directly, but rather use a handy function called zipWith. It takes a binary operation and two lists, and "zips" them together using that binary operation. So something like
zipWith (+) [1, 2, 3] [4, 5, 6] = [1 + 4, 2 + 5, 3 + 6] = [5, 7, 9]
It is rather handy because if one of the lists runs out early, it just stops there. So you could do something like
diff xs = zipWith (-) xs ???
But how do we offset the list by 1? Well, the easy (and safe) way is to use drop 1. You could use tail, but it'll throw an error and crash your program if xs is an empty list, but drop will not
diff xs = zipWith (-) xs $ drop 1 xs
So an example would be
diff [1, 2, 3, 4] = zipWith (-) [1, 2, 3, 4] $ drop 1 [1, 2, 3, 4]
= zipWith (-) [1, 2, 3, 4] [2, 3, 4]
= [1 - 2, 2 - 3, 3 - 4]
= [-1, -1, -1]
This function will return positive and negative values, and we're interested only in the magnitude, so we can then use the abs function:
maxDiff xs = ??? $ map abs $ diff xs
And then using the function I highlighted above:
maxDiff xs = maximum $ map abs $ diff xs
And you're done! If you want to be fancy, you could even write this in point-free notation as
maxDiff = maximum . map abs . diff
Now, this will in fact raise an error on an empty list because maximum [] throws an error, but I'll let you figure out a way to solve that.
As mentioned by bheklilr, maximum is the quick and easy solution.
If you want some of the background though, here's a bit. What we're trying to do is take a list of values and reduce it to a single value. This is known as a fold, and is possible with (among others) the foldl function, which has the signature foldl :: (a -> b -> a) -> a -> [b] -> a.
The (a -> b -> a) section of foldl is a function which takes two values and returns one of the first type. In our case, this should be our comparison function:
myMax :: Ord a => a -> a -> a
myMax x y | x > y = x
| otherwise = y
(note that Ord a is required so that we can compare our values).
So, we can say
-- This doesn't work!
myMaximum :: Ord a => [a] -> a
myMaximum list = foldl myMax _ list
But what is _? It doesn't make sense to have a starting value for this function, so we turn instead to foldl1, which does not require a starting value (instead it takes the first two values from the list). That makes our maximum function
myMaximum :: Ord a => [a] -> a
myMaximum list = foldl1 myMax list
or, in pointfree format,
myMaximum :: Ord a => [a] -> a
myMaximum = foldl1 myMax
If you look at the actual definition of maximum in Data.List, you'll see it uses this same method.
map maps a function over a list. It transforms each thing1 in a list to a thing2.
What you want is to find the biggest difference between two neighbours, which you can't do with map alone. I'll assume you're only looking at numbers for now, because that's just easier.
diffs :: (Num a) => [a] -> [a]
diffs [] = []
diffs [x] = []
diffs (x1:x2:xs) = abs(x1-x2) : (diffs$x2:xs)
mnd :: (Num a, Ord a) => [a] -> a
mnd [] = 0
mnd [x] = 0
mnd xs = maximum$diffs xs
So diffs takes each list item one at a time and gets the absolute difference between it and its neighbour, then puts that at the front of a list it creates at it goes along (the : operator puts an individual element at the front of a list).
mnd is just a wrapper around maximum$diffs xs that stop exceptions being thrown.

What does the : infix operator do in Haskell?

I'm reading A Gentle Introduction to Haskell (which is not so gentle) and it repeatedly uses the : operator without directly explaining what it does.
So, what exactly does it do?
: is the “prepend” operator:
x : xs
Returns a list which has x as first element, followed by all elements in xs. In other functional languages, this is usually called cons, because it “cons”tructs a list recursively by repeated application from an empty list:
1 : 2 : 3 : 4 : []
is the list [1, 2, 3, 4].
Could always check out the types in GHCi/HUGS, as the first steps in the tutorial encourage you to download GHC/HUGS.
Prelude> :t (:)
(:) :: a -> [a] -> [a]
Prelude> :t (++)
(++) :: [a] -> [a] -> [a]
From their respective types, it's quite easy to deduce their usage.
PS: http://haskell.org/hoogle/ is awesome.
The : operator in Haskell is the constructor for lists. It 'cons' whatever is before the colon onto the list specified after it.
For instance, a list of integers is made by 'consing' each number onto the empty list, e.g;
The list [1,2,3,4]
can be constructed as follows:
4 : [] (consing 4 to the empty list)
3 : [4] (consing 3 onto the list containing 4)
2 : [3,4] (consing 2 onto the list containing 3, 4)
1 : [2,3,4] (consing 1 onto the list containing 2,3,4)
giving you;
[1,2,3,4]
Written fully that's;
1 : 2 : 3 : 4 : []
It is the type constructor for lists. It is no different from any other type constructor like Just or Left, except that it is infix. Valid type constructors can either be words starting with a capital letter, or symbols starting with a colon.
So you can define infix constructors for your own data types. For example:
data MyList a = a :> MyList a
| Empty
in the above code we define a type called MyList with two constructors: the first is a weird-looking constructor :> which takes an element and another MyList a; the second is an empty constructor Empty which is equivalent to [] in Haskell's native lists.
The above is equivalent to :
data MyList a = Cons a (MyList a)
| Empty

Resources