Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
pp:syntax [2020/03/12 18:40]
pdmatei
pp:syntax [2020/03/12 23:18] (current)
pdmatei
Line 60: Line 60:
  
 Usually (although not mandatory), functions are defined in //prefix// form (as seen in the previous examples). Some Haskell functions are infix (e.g. ''​+'',​ ''​.''​ or ''​$''​). We can //turn// an infix function into a prefix one using parentheses. E.g. '':​t ($)''​ or ''​(+) 1 2''​. Similarly, we can //turn// an prefix function into an infix, using quasiquotes,​ e.g. ''​1 `f` 2''​ where ''​f x y = x + y''​. ​ Usually (although not mandatory), functions are defined in //prefix// form (as seen in the previous examples). Some Haskell functions are infix (e.g. ''​+'',​ ''​.''​ or ''​$''​). We can //turn// an infix function into a prefix one using parentheses. E.g. '':​t ($)''​ or ''​(+) 1 2''​. Similarly, we can //turn// an prefix function into an infix, using quasiquotes,​ e.g. ''​1 `f` 2''​ where ''​f x y = x + y''​. ​
 +
 +==== where ====
 +
 +Often we would like to define auxiliary functions whose scope (visibility) is limited to our function definition. We can do this using ''​where''​. We illustrate it on several examples:
 +
 +<code haskell>
 +f x y = (inc x) + y
 +          where inc v = v + 1
 +</​code>​
 +
 +<code haskell>
 +f x y = (inc x) + (dec y)
 +          where inc v = v + 1
 +                dec v = v - 1
 +</​code>​
 +
 +<code haskell>
 +f x y = (inc x) + (dec y)
 +          where inc v = (g v) + 1
 +                      where g 0 = 0
 +                            g _ = 1
 +                dec v = v - 1
 +</​code>​
 +
 +<code haskell>
 +f x y = (inc x) + (dec y)
 +          where inc v = (g v) + 1
 +                g 0 = 0
 +                g _ = 1
 +                dec v = v - 1
 +</​code>​
 +
 +The last two examples construct functions ''​f''​ with the same behaviour, however they are not identical. In the latter example, the function ''​g''​ is visible in the entire ''​where''​ body, thus other functions defined in the same scope could employ it.
  
 ===== Basic datatypes ====== ===== Basic datatypes ======
Line 96: Line 129:
 ===== Pattern matching ====== ===== Pattern matching ======
  
-A powerful mechanism in Haskell is pattern matching, which allows ​expressing ​+A powerful mechanism in Haskell is pattern matching, which allows ​defining function body-expressions based on how a value is constructed. In a pattern, only base constructors can be used. The simplest example is: 
 + 
 +<code haskell>​ 
 +f [] = ... 
 +f (x:xs) = ... 
 +</​code>​ 
 + 
 +which defines two body expressions,​ one for an argument equal to the empty list, and one for a list constructed via the //cons// operator. Here, ''​x''​ is the first element of the list and ''​xs''​ is the rest of the list. 
 + 
 +Patterns can be combined liberally to express more complicated arguments such as: 
 +  * ''​(x:​y:​xs)''​ - a list of at least two elements 
 +  * ''​(1:​xs)''​ - a list which contains ''​1''​ as its first element 
 +  * ''​[1,​2]''​ - the list ''​[1,​2]''​  
 +  * ''​(1:​2:​[])''​ - same as above 
 +  * ''​(x,​y)''​ - a pair where ''​x''​ is the first element and ''​y''​ is the second 
 +  * ''​( (x:​xs),​(y:​ys) )''​ - a pair where both the first and the second elements are lists of at least one element 
 +  * ''​_''​ - //​anything//​ - or an anonymous value 
 + 
 +Pattern matching in Haskell is not limited to function definitions,​ but can also be used in the body expression of a function, using ''​case''​ expressions:​ 
 +<code haskell>​ 
 +case <​expression>​ of 
 +   <​pattern 1> -> <body expression 1> 
 +   ... 
 +   <​pattern n> -> <body expression n> 
 +</​code>​ 
 + 
 +The ''<​expression>''​ is evaluated to a value, and the value is hence checked to see if it satisfies each pattern in turn. When a pattern is found, the case expression is evaluated to the pattern'​s respective body expression. 
 + 
 +Example: 
 +<code haskell>​ 
 +case foldr (:) [] [1,2,3] of 
 +  [] -> 1 
 +  (x:xs) -> 2 
 +  (x:y:xs) -> 3 
 +  _ -> 4 
 +</​code>​ 
 + 
 +In the previous example, ''​foldr (:) [] [1,​2,​3]''​ evaluates to ''​[1,​2,​3]''​. The first pattern is not satisfied, however the second one is, thus the case expression will return ''​2''​. The third pattern is more particular but occurs after the first satisfying pattern. 
 + 
 +===== Guards ===== 
 + 
 +Instead of relying on how values are constructed,​ a programmer may want to define a function'​s body expression in terms of boolean conditions. This can be done using **guards**, as follows: 
 + 
 +<code haskell>​ 
 +<​function name> <​param1>​ ... <param n> 
 +   | <boolean condition 1> = <body expression 1> 
 +   ... 
 +   | <boolean condition n> = <body expression n> 
 +   | otherwise = <body expression (n+1)> 
 +</​code>​ 
 + 
 +Example: 
 + 
 +<code haskell>​ 
 +f x y 
 +   | x + 5 > y = 1 
 +   | x == y = 2 
 +   | x == head (sort [x,y]) = 3 
 +</​code>​ 
 + 
 +In the previous example, ''​f 1 5''​ will return ''​1''​ while ''​f 4 5''​ will return ''​3''​. 
  
-  ​