Express a "case ... of" pattern more elegantly in Haskell - haskell

I came across a pattern which I believe can be expressed more elegantly:
I have two functions f1,f2 :: Int -> Int (their impl. is not relevant), and a process :: Int -> Int which does the following:
if f1 x produces x1 different from x, then repeat the process with x1
otherwise, if f2 x produces x2 different from x, then repeat the process with x2
finally, stop the process and return x
My case ... of implementation is the following:
f1 :: Int -> Int
f1 = undefined
f2 :: Int -> Int
f2 = undefined
process :: Int -> Int
process x =
case f1 x of
x ->
case f2 x of
x -> x
x' -> process x'
x' -> process x'
which produces the following warnings:
so.hs:13:17: warning: [-Woverlapping-patterns]
Pattern match is redundant
In a case alternative: x' -> ...
|
13 | x' -> process x'
| ^^^^^^^^^^^^^^^^
so.hs:14:9: warning: [-Woverlapping-patterns]
Pattern match is redundant
In a case alternative: x' -> ...
|
14 | x' -> process x'
| ^^^^^^^^^^^^^^^^
Can anyone shed some light as to what patterns are overlapping, and how to implement process more elegantly?

There is no way to write a pattern for "a value equal to the one I have stored in a variable x". This is because pattern matching is the primary way variables are created in Haskell.
process :: Int -> Int
process x =
Here x is a pattern. It's a very simple pattern, since it just matches any possible value for the argument to process, but you could have written a more structured pattern, or even multiple equations for process matching different patterns for that argument. And within the scope of that pattern match (the entire RHS of process), you have x as a local variable referring to the matched value.
case f1 x of
x ->
Here x is once again a pattern, and once again it is a very simple pattern matching any possible value that was inspected by the case expression. Then you have x as a new local variable referring to the matched value within the scope of the match (everything the RHS of the -> arrow); and because you have created two local variables with the same name x, the most local one shadows the other in the scope where they both apply (so you have no way of referring to the original x in the RHS of the -> arrow, only the new x that is the result of f applied to the original x).
If you think the pattern x in the case expression ought to mean "match a value equal to x", then why should the pattern x in the function argument mean "match anything and call it x"? You can't have your cake and eat it too1.
Haskell makes the rule very simple: a variable appearing in a pattern is always the creation of a new variable to refer to the value that matched the pattern. It is never a reference to an existing variable to check if the matched value is equal to it. Only constructors will be "checked to see if they match"; variables are just bound to whatever is there2.
The same applies to your inner case, where you meant to test the result to see if it was still x but actually just created yet another x shadowing both of the outer x variables.
This is why the compiler complains about your other pattern matches being redundant. Pattern are checked in order, and the first pattern in each case already matches anything (and calls it x), so the second match in each case will never even be tried.
So, since pattern matching can never test whether a value is equal to a variable, you just need to use a construct other than pattern matching! if ... then ... else ... would work fine. You could also use a guard on a pattern.
2 At least not if you want to be able to tell what a pattern means locally, without examining all containing scopes including the entire module and all imports. A hypothetical language could decide the meaning of the pattern based on whether there's already a variable of that name in scope, but I think Haskell makes right call here. Unexpected shadowing sometimes causes tricky bugs, but at least some sign of them is always local. It would be a nightmare if you could change a pattern from a catch-all to an equality check by introducing a global scope variable with the same name (possibly not even in the same module or even package!).
2 This is actually the core reason we have the syntactic distinction between constructors starting with a capital letter and variables starting with a lowercase letter! The language designers wanted it to be easy to tell at a glance which words are constructors to be matched and which are variables to be bound, without having to consider all the constructor names in scope.

Following Ben's advice, I wrote the following:
process :: Int -> Int
process x
| x /= x1 = process x1
| x /= x2 = process x2
| otherwise = x
where
x1 = f1 x
x2 = f2 x

Related

Question on Pattern Matching: Why can I not use the same arguments for a conjuction?

Context from Programming with haskell Textbook Page 32
This version also has the benefit that, under lazy evaluation as
discussed in chapter 12, if the first argument is False, then the
result False is returned without the need to evaluate the second
argument. In practice, the prelude defines ∧ using equations that have
this same property, but make the choice about which equation applies
using the value of the first argument only:
True ∧ b = b
False ∧ _ = False
That is, if the first argument is True, then the result is the value
of the second argument, and, if the first argument is False, then the
result is False. Note that for technical reasons the same name may not
be used for more than one argument in a single equation. For example,
the following definition for the operator ∧ is based upon the
observation that, if the two arguments are equal, then the result is
the same value, otherwise the result is False, but is invalid because
of the above naming requirement:
Question
I do not understand the explanation for not being able to use the expression
b ∧ b = b
__∧_ _= False
To accept a definition such as
myFunction x x = ...
myFunction _ _ = ...
we need to be able to test two values for equality. That is, given two arbitrary values x and y, we need to be able to compute whether x == y holds.
This can be done in many cases, but (perhaps surprisingly) not all. We surely can do that when x and y are Bools or Ints, but not when they are Integer -> Bool or IO (), for instance, since we can not really test functions on infinitely many points, or IO actions on infinitely many worlds.
Consequently, pattern matching is allowed only when variables are used linearly, i.e. when the appear at most once in patterns. So, myFunction x x = ... is disallowed.
If needed, when == is defined (like on Bools) we can use guards to express the same idea:
myFunction x1 x2 | x1 == x2 = ....
| otherwise = ....
In principle, Haskell could automatically translate non-linear patterns into patterns with guards using ==, possible causing an error if == is not available for the type at hand. However, it was not defined in this way, and requires the guard to be explicitly written, if required.
This automatic translation could be convenient but could also be a source of subtle bugs, if one inadvertently reuses a variable in a pattern without realizing it.

NamedFieldPuns, Pattern matching using variable name

{-# LANGUAGE NamedFieldPuns #-}
data Factory = Factory { fId :: Int}
data Link = Link Int Int Double
hasLinkTo :: Factory -> Link -> Bool
hasLinkTo Factory{fId} (Link fId _ _) = True
Got error
• Conflicting definitions for ‘fId’ Bound at: <source.hs> In an equation for ‘hasLinkTo’
I know using variables could fix it,
hasLinkTo Factory{fId=a} (Link b _ _) = a == b
I want to ask for
reason of compilation fail, to better understand how pattern matching work.
is there any idiomatic way to write the function?
for example: if I want to extract what link to a node i, I want to write something like this
connected :: Int -> Link -> (Int, Double)
connected i (Link i j d) = (j,d)
connected i (Link j i d) = (j,d)
Is there any way to check for (==) using only pattern matching on non-numeric literals?
connected 0 (Link 0 j d) = (j,d) is working fine. but the above example won't.
Record punning with Factory{fId} is only syntactic sugar which GHC expands to Factory{fId=fId}. This declared a variable named fId with the value of the field named fId from the Factory record.
Furthermore, pattern matching only declares variables. It does not allow you to compare them by repeating the same name. Consider an attempt to compare equality:
eq a a = True
eq _ _ = False
This is a simple example that tried to do the same thing you are. It will not compile, though.
In the same way, the compiler complains because you declare two variables when you do (Link fId _ _). This is not allowed. Instead you need to use another name and explicitly compare the two:
hasLinkTo Factory{fId} (Link fInd' _ _) = fId == fId'
Haskell only allows linear patterns, where each variable can appear at most once. I believe that this was a deliberate design choice. Theoretically speaking
case e1 of C x x y -> e2 ; ...
could be automatically translated to
case e1 of C x1 x2 y | x1==x2 -> e2 ; ...
This would mean that non linear patterns require an additional Eq constraint for the types of non-linear variables. Further, it could be argued that it is possible for a programmer to accidentally reuse a variable by mistake, which would be silently ignored and lead to the unintended semantics if we allowed non-linear patterns.
Probably, the Haskell designers felt that adding | x1==x2 to a pattern was not too cumbersome and makes the intent more explicit.
For numeric literals, however, they kept this translation. A pattern
case e1 of K 0 y z -> e2 ; ...
does translate to
case e1 of K x y z | x==0 -> e2 ; ...
and does require Eq. Since 0 is not a variable, we no longer have the issues of non-linear patterns.
Anyway, the idiomatic way is to add guards like | x1==x2 to non-liner patterns.
You can't use only pattern matching for this at the moment.

What is the Maybe type and how does it work?

I am just starting to program in Haskell, and I came across the following definition:
calculate :: Float -> Float -> Maybe Float
Maybe a is an ordinary data type defined as:
data Maybe a = Just a | Nothing
There are thus two possibilities: or you define a value of type a as Just a (like Just 3), or Nothing in case the query has no answer.
It is meant to be defined as a way to define output for non-total functions.
For instance: say you want to define sqrt. The square root is only defined for positive integers, you can thus define sqrt as:
sqrt x | x >= 0 = Just $ ...
| otherwise = Nothing
with ... a way to calculate the square root for x.
Some people compare Nothing with the "null pointer" you find in most programming languages. By default, you don't implement a null pointer for data types you define (and if you do, all these "nulls" look different), by adding Nothing you have a generic null pointer.
It can thus be useful to use Maybe to denote that it is possible no output can be calculated. You could of course also error on values less than 0:
sqrt x | x >= 0 = Just $ ...
| otherwise = error "The value must be larger or equal to 0"
But errors usually are not mentioned in the type signature, nor does a compiler have any problem if you don't take them into account. Haskell is also shifting to total functions: it's better to always try at least to return a value (e.g. Nothing) for all possible inputs.
If you later want to use the result of a Maybe a, you for instance need to write:
succMaybe :: Maybe Int -> Maybe Int
succMaybe (Just x) = Just (x+1)
succMaybe _ = Nothing
But by writing Just for the first case, you somehow warn yourself that it is possible that Nothing can occur. You can also get rid of the Maybe by introducing a "default" value:
justOrDefault :: a -> Maybe a -> a
justOrDefault _ (Just x) = x
justOrDefault d _ = d
The builtin maybe function (note the lowercase), combines the two previous functions:
maybe :: b -> (a -> b) -> Maybe a -> b
maybe _ f (Just x) = f x
maybe z _ Nothing = z
So you specify a b (default value) together with a function (a -> b). In case Maybe a is Just x, the function is applied to it and returned, in case the input value is Nothing, the default value will be used.
Working with Maybe a's can be hard, because you always need to take the Nothing case into account, to simplify this you can use the Maybe monad.
Tom Schrijvers also shows that Maybe is the successor function in type algebra: you add one extra value to your type (Either is addition and (,) is the type-algebraic equivalent of multiplication).

function name vs variable in haskell

From haskell documentation:
Identifiers are lexically distinguished into two namespaces (Section 1.4): those that begin with a lower-case letter (variable
identifiers) and those that begin with an upper-case letter
(constructor identifiers).
So a variable containing a constant value, i.e a=4 and the function name add add a b = a + b are both variable identifiers, true? Can we say that a function name is variable?
From another academic source:
f (patter1)...(pattern2) = expression
..where a pattern can be constructor or a variable, not a defined
function
This is where I get confused. As I can do f g x where g is a function, I again see that a function name is a variable then. True?
What do they mean with "not a defined defined function" then?
A function name can be a variable identifier, except when it is an operator like +.
This is a statement about lexical matters.
You can't infer from that that a function name is a variable. (Because a variable is not a lexical thing.)
It is the other way around, like in
f . g = \a -> f (g a)
where f and g are variables, i.e. names that are bound to some unknown-in-advance values, but we know that those values must be functions.
A named function is indeed just a global variable who's "value" just happens to be a function. For example,
id x = x
can just as well be written as
id = ( \ x -> x )
Haskell explicitly makes no distinction between these two. Even the type signature says it:
id :: x -> x
So id is just a value who's value has type x -> x (i.e., a function).
Somebody else said something about operators not being variables; this is untrue.
let (<+>) = \ x y -> (x+y)/(x*y) in 5 <+> 6
You can even do something utterly horrifying like write a loop where the contents of <+> changes each time through the loop. (But why in the hell would anybody ever do that?)

What type of scope does Haskell use?

I'm trying to figure out if Haskell uses dynamic or static scoping.
I realize that, for example, if you define:
let x = 10
then define the function
let square x = x*x
You have 2 different "x's", and does that mean it is dynamically scoped? If not, what scoping does it use, and why?
Also, can Haskell variables have aliases (a different name for the same memory location/value)?
Thanks.
Haskell use (broadly speaking) exactly the same lexical scoping as most other languages.
eg.
x = 10
Results in a value referenced through x in the global scope, whereas
square x = x * x
will result in x being lexically scoped to the function square. It may help if you think of the above form being a syntactic nicety for:
square = \ x -> x * x
As to your other question i'm not sure what you mean by aliasing
Answering only the second part of the question:
You can have several aliases for the same "memory location", but since they are all immutable, it does not matter most of the time.
Dumb example:
foo x y = x * y
bar z = foo z z
When within foo called from bar, both x and y are clearly the same value. But since you cannot modify either x or y, you will not even notice.
There are some things wrong in your statements...
There are no mutable variables in Haskell just definitions (or immutable variables)
A variable memory location is a concept that do not exist in Haskell
In your example, x is not 10 in the function is just a argument to square, that can take any value (you can specify the type later) in this case 10 but just in this case.
Here is an example of aliases provided by Curt Sampson:
import Data.IORef
main :: IO ()
main = do x <- newIORef 0 -- write 0 into x
readIORef x >>= print -- x contains 0
let y = x
readIORef y >>= print -- y contains 0
writeIORef x 42 -- write 42 into x
readIORef y >>= print -- y contains 42
As the first part of the question is already answered by others, here is the second part:
I assume by aliasing you mean one name for another. As haskell is a functional language, and functions behave as normal identifiers in any case, you can do that like this:
y = x
which would define an alias y for the function x. Note that everything is a function. Even if it looks like a "variable", it's just a nullary function taking no arguments. Aliases for types look like this:
type Function = Double -> Double
which would define an alias Function for the type Double -> Double
Haskell uses static nested scopes. What is a bit confusing compared with other languages that have static nested scopes is that the scope of a name is a block which includes tests preceding its definition. For example
evens = 0 : map (+1) odds
odds = map : (+1) evens
here the name 'odds' is in scope in the definition of 'evens', despite the surprising fact that 'odds' has not yet been defined. (The example defines two infinite lists of even and odd numbers.)
A dead language with a similar scoping rule was Modula-3. But Haskell is a bit trickier in that you can attempt to 'redefine' a variable within the same scope but instead you just introduce another recursion equation. This is a pitfall for people who learned ML or Scheme first:
let x = 2 * n
x = x + 1 -- watch out!
This is perfectly good ML or Scheme let*, but Haskel has scheme letrec semantics, without the restriction to lambda values. No wonder this is tricky stuff!
In your example, the global definition of x is shadowed by the local definition of x. In Haskell, a variable's scope is determined by a static reading of the source code - this is called lexical scope, but can get something similar to dynamic scoping with implicit parameters (but that can lead to some unexpected behavior (I've read; never tried 'em myself)).
To sum up the other answers concisely:
lexical scope
aliasing is as easy as x = 1; y = x but doesn't usually matter because things are immutable.
The let syntax you use in your example looks like it's at the interactive ghci> prompt. Everything in interactive mode occurs within the IO monad so things may appear more mutable there than normal.
Well, as I think people have said already, Haskell doesn't have any variables as found in most other languages, it only has expressions. In your example let x = 10 x is an expression that always evaluates to 10. You can't actually change the value of x later on, though you can use the scoping rules to hide it by defining x to be another expression.
Yes, Haskell has aliases. Try out this little program:
import Data.IORef
main :: IO ()
main = do x <- newIORef 0 -- write 0 into x
readIORef x >>= print -- x contains 0
let y = x
readIORef y >>= print -- y contains 0
writeIORef x 42 -- write 42 into x
readIORef y >>= print -- y contains 42

Resources