Values of variables for pattern matching - haskell

Just staring with Haskell. I want to define some elements to easily create morphisms between them.
a = "foo"
b = "bar"
g a = a --Problem is here
g b = a --Problem is here
Edit The problem is that haskell treats "a" in "g a" as a variable, but I actually want the value of the "a" defined above. Conceptually a want this
g (valueOf a) = a --Problem is here
g (valueOf b) = a --Problem is here
Where valueOf is a magic function that would give me
g "foo" = a
g "bar" = a

Use
a = "foo"
b = "bar"
g x | x==a = a
| x==b = a
or
g "foo" = a
g "bar" = a
When you pattern match using a variable as in
g a = ...
the variable a is a local variable, bound to the argument of the function. Even if a was already defined globally, the code above will not use the value of the global a to perform a comparison.
This semantics allows to reason locally about your code. Consider this code as an example:
f 2 x = 4
f c d = 0
Just by looking at the above definition you can see that f 2 3 is 4. This is not changed if later on you add a definition for x as follows:
x = 5
f 2 x = 4
f c d = 0
If the match semantics compared the second argument to 5, now we would have f 2 3 equal to 0. This would make reasoning about the function definitions harder, so most (if not all) functional languages such as Haskell use "local" variables for pattern matching, ignoring the possible global definitions for such variables.
A more adventurous alternative is to use view patterns:
{-# LANGUAGE ViewPatterns #-}
a = "foo"
b = "bar"
g ((==a) -> True) = ...
g ((==b) -> True) = ...
I am not a fan of this approach though, since I find standard patterns with guards to be clearer.

Apologies in advance if this is a complete misunderstanding of what
you want to accomplish but wouldn't something like this do?
Data Obj = A | B
g A = A
g B = A
f A = "foo"
f B = "bar"
You want a predefined set of objects, yes?

Related

Why does matching this function parameter seprately work, but not with guards. (Haskell)

So, I have been trying to use SDL to make a simple GUI. This is so that I start to understand how to use haskell. In this case, I was using https://github.com/palf/haskell-sdl2-examples/blob/master/examples/lesson04/src/Lesson04.hs as reference.
Pay attention, in particular to payloadToIntent on line 72.
payloadToIntent :: SDL.EventPayload -> Intent
payloadToIntent SDL.QuitEvent = Quit
payloadToIntent (SDL.KeyboardEvent k) = getKey k
payloadToIntent _ = Idle
This works perfectly. However, when I change the code to the following, it produces an error. Why does it happen, as to my (admittedtly novice) eyes, this looks equivalent.
payloadToIntent e
| e == SDL.QuitEvent = Quit
| e == SDL.KeyboardEvent k = getKey SDL.KeyboardEvent k
| otherwise = Idle
Error:
src/Events/Intent.hs:15:28: error:
Variable not in scope: k :: SDL.KeyboardEventData
|
15 | | e == SDL.KeyboardEvent k = getKey SDL.KeyboardEvent
| ^
I am using these language extensions: OverloadedStrings, GADTs, PatternGuards
So why did this happen? How could I fix this? Which one would be more idiomatic haskell?
(==) is a function that takes two values of the same type and compares them for equality, returning a Bool. SDL.KeyboardEvent k is not a value of any type (since k is unbound), so you can't compare it with (==).
The idiomatic "choice" is the one that works, i.e. pattern matching. If you want something that has a similar appearance, you can pattern match with case...of instead:
payloadToIntent e = case e of
SDL.QuitEvent -> Quit
SDL.KeyboardEvent k -> getKey k
_ -> Idle
The key idea here is: patterns define variables, bringing them into scope, while expressions do not, requiring all the variables in them to be already defined.
The guard e == SDL.KeyboardEvent k is a boolean valued expression, not a pattern. This is calling function (==) with two arguments: e and SDL.KeyboardEvent k. Your definition, to the compiler, looks like:
payloadToIntent e
| isEqual e SDL.QuitEvent = Quit
| isEqual e (SDL.KeyboardEvent k) = getKey SDL.KeyboardEvent k
| otherwise = Idle
The compiler can not call the equality-test function without passing it the arguments. For that, it needs variable k to be in scope, i.e., to be defined somewhere else.
To stress the point, consider this non-working code:
isSquare :: Int -> String
isSquare n | n == m*m = "It's the square of " ++ show m
| otherwise = "It isn't a square"
This would magically invert the squaring, if possible. That is, however, asking too much to the compiler, which won't magically solve the equation for us. (Indeed, the solution could even fail to be unique!)
As an even more cumbersome case:
f x | x == F y || x == G z = ...
Even if this worked, can we use y or z in the final ...? Probably not. Why should then this be allowed?
Finally, note that, even in those cases where it could work, allowing expressions guards to define variables could be a bad idea. Consider this:
c :: Int
c = 7
f x | x == F c = "Hi"
| otherwise = "there"
Now, is the c in F c a new local variable which is defined on the spot, or is it the constant 7 defined above? If we call f (F 6) do we get Hi (c was a new variable) or there (c was 7)?
Pattern matching avoids this issue by requiring a distinct syntax.

Errors while creating a power function

First of all, I want to say that I'm very very inexperienced with Haskell, and I know that I have done something (or multiple things) terribly wrong, been struggling for hours but I can't seem to find it.
power :: Int -> Int -> Int
power x y | y == 0 = 1
| x == 0 = 0
list = replicate y x
foldr (*) x list
main = print $ power 3 5
Error most of the time is either x and y not being passed to the replicate function or that foldr is a naked function, I understand what they both mean but have no idea on how I can pass the variables or come up with a solution.
You here created four functions: power, list, foldr and main. But you use variables x and y in the definition of the list function.
You can work with a where clause to specify subexpressions, for example:
power :: Int -> Int -> Int
power x y | y == 0 = 1
| x == 0 = 0
| otherwise = foldr (*) 1 list
where list = replicate y x
or perhaps more elegant with pattern matching:
power :: Int -> Int -> Int
power 0 _ = 0
power x y = foldr (*) 1 (replicate y x)
main = print $ power 3 5
Here we can also eliminate the case for x0, since our foldr starts working with 1, not x.
This algorithm is however not very efficient, since it is linear in the value of y. By checking recursively if the exponent is even or odd, you can make it faster. I leave this as an exercise.
You were very close! The main things that need to be fixed are:
When writing a definition with guards, the “fallback” case needs to be a guard as well, conventionally written with otherwise.
Recall that a definition without guards looks like this, with one left side (a name and parameter patterns/names) and one right side (an expression):
name patterns = expression
With guard conditions, there is one right-hand side for each guard:
name patterns | condition1 = expression1
| condition2 = expression2
…
| otherwise = expressionn
otherwise is really just an alias for True, that is, such a guard always matches. The only thing special about otherwise is that the compiler uses it as a hint when analysing whether a pattern match covers all possible cases.
In order to define a variable list, local to the definition of power, using the parameters x and y, you need to use either a let…in… expression, that is, let block in expression, or a where clause, equation where block. A block is a series of items (in this case, local definitions) which must all be written starting at the same column of indentation, or be delimited by explicit curly braces {…} and semicolons ;.
Using let…in… follows the structure of your original code pretty closely. I will adjust the indentation style to avoid needing to align anything, by putting a newline and a constant amount of indentation instead.
power :: Int -> Int -> Int
power x y
| y == 0 = 1
| x == 0 = 0
| otherwise = let
list = replicate y x
in foldr (*) x list
main :: IO ()
main = print $ power 3 5
Attaching a where clause to an equation is slightly more common than using a let…in… expression on the right side of an equation.
power :: Int -> Int -> Int
power x y
| y == 0 = 1
| x == 0 = 0
| otherwise = foldr (*) x list
where
list = replicate y x
main :: IO ()
main = print $ power 3 5
Note that in this case, there is a slight difference: the variable list is visible in all of the right-hand sides, although we only use it in one of them. With let list = … in e, list is only defined within e. In general, it’s helpful for readability to keep the scope of a variable as small as possible, although you can certainly go overboard:
a = …
where
b = …
where
c = …
where
d = …
-- If you see this much nesting, rethink!
If you run into issues with alignment and indentation, you can always use explicit delimiters instead. The code I wrote is equivalent to the following.
power :: Int -> Int -> Int; -- Begin ‘power’ signature.
power x y
| y == 0 = 1
| x == 0 = 0
| otherwise = let { -- Begin ‘let’ block.
list = replicate y x; -- End ‘list’ equation.
} in foldr (*) x list; -- End ‘let’ block, then end ‘power’ equation.
main :: IO (); -- Begin ‘main’ signature.
main = print $ power 3 5; -- End ‘main’ equation.
Or similarly with where { … }.

memoization in Elm

I am trying to write a pseudo-random generator in Elm (to generate points on a screen) but not so easy since it interferes with the ``purity" of the Elm compiler.
OK, so why not write our own function? We can get sort-of random behavior if we write stuff like:
-- initial state
randomNumbers = [ 1 ]
x = 1
b = 2
n = 2017
-- generate random numbers
x = (x*b) % n
randomNumbers = x :: randomNumbers
This does not follow Elm's rule of variable assignments. Something is wrong.
All I am doing is finding the power of 2 mod 2017. The first few are easy but then the sequence gets unpredictible. So I need to keep track of the last number computed.
[ 1, 2, 4, 8, ... , 1024, 31, 62, 124, ...]
Even if I try to use special properties of arithmetic I still have to compute this sparse list of powers
[ 1, 2^1, 2^2, 2^4, 2^8, 2^16, ... ]
can I can solve by successive squaring, but I still need some way to memorize the last step.
I thought... as long as I write my own code, I don't have to import randomness from the "real world" to generate my fair numbers. This way respecting the pureness of Elm. However, I end up writing something that is stateful.
Elm does have a random-number generator now - an implementation of some algorithm - in the Random library, returning a generator type.
This repl session has been quite instructive:
> import Random exposing (..)
>
> initialSeed 0
Seed {
state = State 1 1 ,
next = <function>,
split = <function>,
range = <function>
}
: Random.Seed
> seed0 = initialSeed 101
Seed {
state = State 102 1, ,
next = <function>,
split = <function>,
range = <function>
}
: Random.Seed
> step ( int 0 10 ) seed0
(10,Seed { state = State 4081428 40692, ,
next = <function>,
split = <function>,
range = <function>
}
: ( Int, Random.Seed )
Even with my simplified baby random number generator, what is so stateful here?
My apologies in advance if I say memoizaton when I mean dynamic programming or the other way around
What is the difference between memoization and dynamic programming?
If I could write a stateful function f that remembered things, I could generate all my values with just one line:
List.map f [1..100]
two candidates:
A
https://github.com/elm-community/list-extra/blob/3.1.0/src/List/Extra.elm
iterate : (a -> Maybe a) -> a -> List a
iterate f x =
case f x of
Just x' -> x :: iterate f x'
Nothing -> [x]
B
https://github.com/elm-community/elm-lazy-list/blob/1.3.0/src/Lazy/List.elm
{-| Create an infinite list of applications of a function on some value.
Equivalent to:
x ::: f x ::: f (f x) ::: f (f (f x)) ::: ... -- etc...
-}
iterate : (a -> a) -> a -> LazyList a
iterate f a =
lazy <|
\() ->
Cons a (iterate f (f a))

Using data types in Haskell

I have started this a new question as it became a follow-on from my previous question.
If I have two data types which are composed of similar constructors:
data A = X | Y | Z
data B = X | Y
is there no way I can somehow represent this as:
data A = C | Z
data B = C
data C = X | Y
if you can see what I am doing- I am trying to group the X | Y into one data type, which can then be used by multiple other data types. I cannot seem to get the compiler to allow this, or if it does, I cannot pattern-match against the X or Y, only the C??
I get the error message that C has been declared multiple times.
I thought I could maybe use types, but they do not allow multiple typings.
EDIT
Even if I declare the long way (like below), it still won't compile and says X and Y have multiple declarations:
data A = X | Y | Z
data B = X | Y
Not only can't you do this, you also can't do your first option - i.e. you can't have two types in the same module that both have constructors named X and Y.
If you could do this, what should the type of X be - C, A or B? The most obvious answer would be C, but then you wouldn't be able to use it in a context where an A or a B are required (note that Haskell has no subtyping), so that would defeat the purpose of the whole construct.
The best you can do is to wrap C in a constructor of A and B, i.e.:
data A = AC C | Z
data B = BC C
data C = X | Y
Then you could wrap a C with either the AC or the BC constructor to create a value of type A or B respectively.
The reason you can't do this
data A = X | Y | Z
data B = X | Y
is as follows. Say you write some code later on:
foo n = (n,X)
which builds a pair consisting of n in the first slot and X in the second slot. What type should the compiler infer? A valid type would be
foo :: a -> A -> (a,A)
since X is a constructor of type A, but equally valid is
foo :: a -> B -> (a,B)
since X is a constructor of type B. If you have two constructors with the same name, you can't infer a unique type for functions that use them. So you are disallowed from giving two constructors in the same module the same name.
You can't do this:
data A = C | Z
data B = C
data C = X | Y
(As an aside, if B is identical to C, then why have B at all?)
But what you can do is something like this:
data A = A_Other C | Z
data B = B_Other C
data C = X | Y
Then you can pattern match like this:
foo :: A -> String
foo (A_Other X) = "X"
foo (A_Other Y) = "Y"
foo ( Z) = "Z"
bar :: B -> String
bar (B_Other X) = "X"
bar (B_Other Y) = "Y"
foobar :: C -> String
foobar X = "X"
foobar Y = "Y"
If that makes sense...
You cannot do what you want because you are declaring multiple data constructors. In
data A = X | Y | Z
You are actually introducing the type A which has 3 constructors (values) X, Y, and Z. This is why your first piece of code won't compile, it sees the same name listed as constructors for two different types! If you could do this you'd have to ask yourself is
X :: A
or
X :: B
which in a non object-oriented context is scary! So you need to provide different constructor names to share that underlying data, C.
If you want to factor this, you can do as the other posts have suggested and factored-out data in unique constructors for each datatype
data A = CForA C | Z
data B = CForB C
data C = X | Y

Haskell - pattern matching syntactic sugar and where

Often I have a function of such pattern:
f :: a -> b
f x = case x of
... -> g ...
... -> g ...
...
... -> g ...
where g = ...
There is an syntactic sugar for almost this case:
f :: a -> b
f ... = g ...
f ... = g ...
...
f ... = g ...
Unfortunately I can't attach my where to it: I'll obviously get bunch of not in scopes.
I can make g a separate function, but it's not nice: my module's namespace will be polluted with utility functions.
Is there any workaround?
I think that your first example isn't bad at all. The only syntactic weight is case x of, plus -> instead of =; the latter is offset by the fact that you can omit the function name for each clause. Indeed, even dflemstr's proposed go helper function is syntactically heavier.
Admittedly, it's slightly inconsistent compared to the normal function clause syntax, but this is probably a good thing: it more precisely visually delimits the scope in which x is available.
No, there is no workaround. When you have multiple clauses for a function like that, they cannot share a where-clause. Your only option is to use a case statement, or do something like this:
f x =
go x
where
go ... = g ...
go ... = g ...
g = ...
...if you really want to use a function form for some reason.
f = g . h -- h is most of your original f
where h ... = ...
h ... = ...
g =
From Haskell 2010 on, or with GHC you can also do:
f x
| m1 <- x = g
| m2 <- x = g
...
where g =
but note that you cannot use the variables bound in the patterns in g. It's equivalent to:
f x = let g = ... in case () of
() -> case x of
m1 -> g
_ -> case x of
m2 -> g
....
Your original solution seems to be the best and only workaround. Syntactically it's not any heavier than direct pattern matching on function parameters if not even lighter.
But just in case if what you need is just to check preconditions and not pattern match don't forget about guards, which allow you to access the where scope freely. But really I see nothing bad in your case of solution.
f :: a -> b
f a
| a == 2 = ...
| isThree a = ...
| a >= 4 = ...
| otherwise = ...
where isThree x = x == 3
With LambdaCase, you can also do this:
{-# language LambdaCase #-}
f :: a -> b
f = \case
... -> g ...
... -> g ...
...
... -> g ...
where g = ...
Is it safe to assume that you consistently use g on most, if not all, of the different branches of the case statement?
Operating with the assumption that f :: a -> b for some a and b (possibly polymorphic), g is necessarily some function of the form c -> d, which means that there must be a way to consistently extract a c out of an a. Call that getC :: a -> c. In that case, the solution would be to simply use h . g . getC for all cases, where h :: d -> b.
But suppose you can't always get the c out of an a. Perhaps a is of the form f c, where f is a Functor? Then you could fmap g :: f c -> f d, and then somehow transform f d into a b.
Just sort of rambling here, but fmap was the first thing that came to mind when I saw that you appeared to be applying g on every branch.

Resources