I have to convert a Haskell type signature into a term.
The type signature is :
f :: (a -> b -> c) -> (d -> b) -> (d -> a) -> d -> c
The correct resulting term is :
f g h j x = g (j x) (h x)
and here lies my problem as I understand it g is a function which returns a function which returns c and c is function which returns a function d which returns b and b is a function which returns itself which then returns itself again which then returns c.
Correct me if i am wrong.
What I don't get is why is g taking (j x) as first argument and (h x) as second argument. Shouldn't it be the other way around? Haskell is right associative and h is the secound parameter given to the function f and not j.
g :: a -> b -> c, h :: d -> b, j :: d -> a, and x :: d are all independent arguments to f; their order implies nothing about how we might end up using them in the definition of f.
To start, we know that f uses its arguments to return a value of type c. But none of the arguments have a value of type c; the only way to get a value of type c is to use g. But in order to use g, you need arguments of type a and type b, and none of f's arguments have those types. But we could use h and j to get them, if we had an argument of type d to apply them to, and lo and behold, we do have a value of type d: the argument x!.
f g h j x = let aValue = j x
bValue = h x
cValue = g aValue bValue
in cValue
which can be flattened to the original answer of
f g h j x = g (j x) (h x)
If you want to think of the return value of f as being d -> c, rather than just c, you can eliminate x from the definition with some point-free trickery.
f g h j = g <$> j <*> h -- liftA2 g j h
You can even go a little further to remove h and j as arguments, but the result, though simple, is even more incomprehensible:
f = flip . liftA2
Moral of the story: sometimes point-free style abstracts away distracting details, other times it completely obscures the meaning of the function.
Related
I am learning higher-order functions from 'Learn You a Haskell for Great Good!' by Miran Lipovaca.
For the following function flip which takes a function and returns a function with the first two arguments flipped:
flip' :: (a -> b -> c) -> (b -> a -> c)
flip' f = g
where g x y = f y x
I don't exactly understand what f and g are. Are they two different functions? Similarly, in the where binding, what exactly does g x y = f y x mean?
In the syntax:
myFunction x = x + 2
things on the left hand side of the equal sign, x, are treated as "parameters". You can use them on the right hand sign of the equal sign to state what you want the result to be.
This syntax defines a function myFunction, with single parameter x.
So here we have:
flip' f = g
This defines a function flip', with single parameter f.
We have another definition, as well:
g x y = f y x
This defines a function g, with two parameters, x and y.
So when we say:
flip' f = g
where
g x y = f y x
We are saying that the result of flip f is the function g, where g is defined as g x y = f y x.
In case the short variable names are confusing you, here is the same function with some of the names swapped for clarity:
flippity flop = glop
where
glop x y = flop y x
See if you can understand what flippity does, and see if you can see how it is the same as flip', just with different internal parameter and helper function names.
Remember also in Haskell that we can always replace function calls by their body, for the most part. So we can rewrite that as:
flippity flop = glop
where
glop = \x y -> flop y x
-- replace glop with its definition
flippity flop = \x y -> flop y x
So we can see that flippity is a function that takes a function flop and returns a new function, \x y -> flop y x.
f is flip''s input (the function you want to flip), g is flip's output (the flipped function it will return).
The where clause is simply defining what g is; that is, defining a function that simply calls f with its arguments reversed.
You could avoid naming g at all by simply having flip' return a lambda:
flip' :: (a -> b -> c) -> (b -> a -> c)
flip' f = \x y -> f y x
So I've been trying to convert this Haskell function thats checks if a list doesn't have any repetitions into an Hylomorphism, but there's something odd about it.
valid :: [a] -> Bool
valid [] = True
valid (h:t) = if (not (elem h t)) then valid t else False
I'll be glad if anyone can help! Thx
Well a hylomoprhism is a function h : A → C that can be defined in an anamoprhism (g and p) and catamorphism (c and ⊕) part.
The anamorphism part consists of a function g : A → B × A that "unfolds" the object into smaller parts, and p : A → Bool a predicate that determines if we are done unfolding.
The catamorphism part consists of a value c ∈ C and an operator ⊕ : B × C → C.
(this text is a slightly modified version of the Wikipedia page)
In your case the unfolding means that we unfold a list in some value (of type B, and a recursive part, that is here the tail of the list.
The predicate p can be derived out of your definition: if the list is empty, then we have terminated. It is clear that in that case we return True, so that means c is True.
So now what would the B part be? Well if we look at your function we need access to both the head and the tail of the list, so B can be seen as a 2-tuple containing the head (as first element), and a tail (as second element).
So now the remaining question is what ⊕ does? It takes as input a 2-tuple of type E×[E] (pseudo-Haskell notation), and a boolean (type C which is a Bool). As we can see, it checks if the head is en element of the tail. If that is the case, it returns False, and ignores the recursive part, otherwise it returns the recursive part.
So we can write this in Haskell like:
-- types
type A e = [e]
type B e = (e, [e])
type C = Bool
-- functions
p :: A e -> Bool
p [] = True
p (_:_) = False
g :: A e -> (B e, A e)
g (h:t) = ((h, t), t)
c :: C
c = True
plus :: Eq e => B e -> C -> C
plus (h, t) r | elem h t = False
| otherwise = r
hylo :: Eq e => A e -> C
hylo a | p a = c
| otherwise = plus b (hylo a')
where (b, a') = g a
hylo is thus a straighforward implementation based on the definition where we thus take the functions p, c, plus and g as "building blocks".
This question already has answers here:
How do I use fix, and how does it work?
(5 answers)
Closed 6 years ago.
So I am reading Paul Hudak's book "The Haskell School of Expression" and am stuck on an exercise in there.
Here it goes
Suppose function fix is defined as
fix f = f (fix f)
What is the principal type of fix? That one I know, it's b -> b -> b
But I don't understand the way fix is defined, won't it go into an infinite recursion?
Also, let the remainder function be defined as
remainder :: Integer -> Integer -> Integer
remainder a b = if a < b then a
else remainder (a - b) b
Rewrite remainder using fix so that it is non-recursive.
First of all the principal type of fix is actually (b -> b) -> b (remember that only b -> (b -> b) is the same as b -> b -> b).
In a strict language, such a definition would go into infinite recursion, but because Haskell is lazy, the arguments to a function are evaluated only if they are at any point needed. For example you can define factorial.
-- with recursion
factorial :: Int -> Int
factorial n = if n == 0 then 1 else n * factorial (n-1)
-- with `fix`
factorial' :: Int -> Int
factorial' = fix (\f n -> if n == 0 then 1 else n * f (n - 1))
Following the same pattern, you should be able to define remainder.
Playing with it a little gives us
fix f = f (fix f) -- definition
fix f a = f (fix f) a -- eta expansion
fix f a b = f (fix f) a b -- eta expansion
remainder a b = if a < b then a else remainder (a - b) b -- definition
-- we want remainder = fix f: -- equation
fix f a b = if a < b then a else (fix f) (a - b) b -- substitution
= (\g -> if a < b then a else g (a - b) b) (fix f) -- abstraction
= fix (\g -> \a b -> if a < b then a else g (a - b) b) a b -- abstraction
thus
remainder =
fix (\g a b -> if a < b then a else g (a - b) b) -- eta reduction
I would like to define a function that operates on an expression of a certain type, but has access to its internal structure, if it has one. For instance, f in what follows:
g :: a -> a -> a
g x y = y
f :: a -> a
f x'#(g x y) = x'
f _ = 1
(g x y) is of type a, so f should be able to take it as an argument, but the definition for f above can't be parsed by Haskell. I would like to define something like f to take advantage of call-by-name evaluation. Is there any way to do this in Haskell?
First, pattern matching is allowed only on patterns, i.e. expressions built from application, constructors, and variables (used at most once).
Second, even if it were extended, your example is problematic because your g is not injective:
case g x y of g a b -> a
should be equal to, since g x y = y
case y of g a b -> a
but then a could be anything.
If instead it happens that g is defined by an expression which could be a pattern, then GHC can allow using it as a pattern if you ask for it through the PatternSynonyms GHC extension.
pattern G a b = ("hello", b, a)
foo = case someTriple of
G a b -> use a b
(s, x, y) -> ...
bar = G 4 5 -- we can also use G as a function
Haskell newbie here. I was going through Learn you a haskell, and came across this definition of the flip function.
flip' :: (a -> b -> c) -> (b -> a -> c)
flip' f = g
where g x y = f y x
What I don't get is, where did x and y come from? I mean, the signature tells me that flip' is a function that takes a function (with two parameters), and returns a function (again, with two parameters).
If I'm understanding this right, when I write a function which goes like
foo :: (a -> b) -> a -> b
foo f x = f x -- applies the function f on x
But then, in this case I'm passing the parameter explicitly [ ie x ] and so I'm able to access it in the function body. So how come the flip' function can access the parameters x and y?
The Prelude, which is in the base package at hackage.haskell.org, is included with an implicit import in every Haskell file is where the flip function is found. On the right side you can click "source" and see the source code for flip.
flip :: (a -> b -> c) -> b -> a -> c
flip f x y = f y x
The where clause allows for local definitions, x=10 or y="bla". You can also define functions locally with the same syntax you would for the top level. add x y = x + y
In the below equivalent formulation I make the substitution g = f y x
flip :: (a -> b -> c) -> b -> a -> c
flip f x y = g
where
g = f y x
Right now g takes no parameters. But what if we defined g as g a b = f b a well then we would have:
flip :: (a -> b -> c) -> b -> a -> c
flip f x y = g x y
where
g a b = f b a
No we can do a little algebraic cancelation(if you think of it like algebra from math class you will be pretty safe). Focusing in on:
flip f x y = g x y
Cancel the y on each side for:
flip f x = g x
Now cancel the x:
flip f = g
and now to put it back in the full expression:
flip :: (a -> b -> c) -> b -> a -> c
flip f = g
where
g a b = f b a
As a last cosmetic step we can make the substitution a to x and b to y to recover the function down to argument names:
flip :: (a -> b -> c) -> b -> a -> c
flip f = g
where
g x y = f y x
As you can see this definition of flip is a little round about and what we start with in the prelude is simple and is the definition I prefer. Hope that helps explain how where works and how to do a little algebraic manipulation of Haskell code.
flip' doesn't access x and y. It receives an argument f, and evaluates to the expression g. No x or y in sight.
However, g is itself a function, defined with an auxiliary equation in the where clause of flip'.
You can read g x y = f y x exactly as if it were a top level equation like flip'. So g is a function of two arguments, x and y. It's g that has access to x and y, not flip'. Values for those arguments don't exist until g is applied, which is not until after flip' has returned the function g (if ever).
The thing that's special that about g being defined in the where clause of flip' is that it can have access to the arguments of flip', which is how g can be defined in terms of f.
So when flip' is invoked it receives a function f. For each particular invocation of flip', it constructs a new function g. g would receive two arguments, x and y, when it is called, but that hasn't happened yet. flip' then just returns g as its result.
One simple example to understand and illustrate, on your ghci do:
Prelude> sub x y = x - y
Prelude> sub 3 1
2
Prelude> flip sub 3 1
-2
Let's find the type of g.
We know flip type : (a -> b -> c) -> (b -> a -> c)
Therefore we can deduce f type : (a -> b -> c)
We have this definition for g
g x y = f y x
From the right-hand-side we deduce that y :: a and x :: b.
Hence g :: b -> a -> c
Note that the definition could be rewritten without the 'where' clause.
flip' f = g where g x y = f y x
-> flip' f a b = g a b where g a b = f b a
-> flip' f a b = f b a
Put simply, you can also define functions in a where block. So the variables x and y are just the formal parameters of g, and that's why you can access it in g x y = f y x: g x y defines formal parameters x and y, and f y x is the definition of what g does. Finally, that definition is returned from flip f = g.