One past exam question was to state the type of the function ring with definition ring r q p = r (q p). Supposedly the answer is ring :: (b -> c) -> (a -> b) -> (a -> c), but I don't see where this comes from. Surely such a type would indicate that ring only receives two arguments, but in the definition it takes three, so what's going on?
Every function in Haskell takes one parameter. A function can however return a function that takes another parameter. Haskell however introduces some syntax to make it more convenient. A signature (b -> c) -> (a -> b) -> (a -> c) is thus equivalent to (b -> c) -> ((a -> b) -> (a -> c)) or (b -> c) -> (a -> b) -> a -> c.
Let us first analyze the expression:
ring r q p = r (q p)
Since at the moment we do not know much about the type yet, we will first assign some types to the parameters:
r :: a
q :: b
p :: c
ring :: a -> b -> c -> d
Now we can start to determine the types. In the expression, we see q p, this thus means that q is a function, and p a parameter. This thus means that q is a function of type c -> e (with e a type parameter we introduce).
So we derived that:
q :: c -> e
p :: c
q p :: e
Next we see that the result of q p is used as a parameter with r the function, so that means r is a function that takes an e as parameter type. We thus set the type of r to e -> f. We thus know that:
q p :: e
r :: e -> f
r (q p) :: f
Since the result of ring r q p is r (q p), this thus means that the type of ring is:
ring :: (e -> f) -> (c -> e) -> c -> f
or more verbose:
ring :: (e -> f) -> ((c -> e) -> (c -> f))
Let's go step by step into you ring function (known for everybody as compose or .)
here is the story:
ring r q p = r (q p)
if you start with p you can give to it a type, the variable is not bounded or restricted, so it can be variable, generic, so let's choose a name, a
p :: a
now, q has something that you can tell, it takes values of type p as parameter, right? Because it is applied to p , (q p), so, q is a function, and a function has the form (type -> type),
p :: a
q :: (type -> type)
now you can replace the input, q expects a p typed values, and p :: a so:
p :: a
q :: a -> type
again, the type of the return can be the same as the input, but is not restricted to be, so we can use another name to it, let use b
p :: a
q :: a -> b
(q p) :: b
now, what about r ?, r expects the result of (q p) and you know the type, it is b, same logic, r :: type -> type because it is a function
p :: a
q :: a -> b
(q p) :: b
r :: b -> type
and finally, the return type of r is not restricted, so it can be a c type, so:
p :: a
q :: a -> b
(q p) :: b
r :: b -> c
r (q p) :: c
replacing everything in ring:
ring :: (b -> c) -> (a -> b) -> a -> c
ring r q p = r (q p)
see that I didn't use the final parenthesis, because they are not needed, in haskell the functions are curried, so, its true that if you give two functions to ring, it will return a third function of type a -> c
let's see:
ring show (+1)
(+1) :: Num a -> a -> a
show :: Show a => a -> String
ring show (+1) :: (Show a, Num a) => a -> String
and I didn't give the value, so that why you can write ring as:
ring :: (b -> c) -> (a -> b) -> (a -> c)
and remove it to:
ring :: (b -> c) -> (a -> b) -> a -> c
and to see more, check the types of:
ring show :: Show a => (b -> a) -> b -> String
ring show (+1) :: (Show a, Num a) => a -> String
ring show (+1) 2 :: String
ring also can have more extra parenthesis:
ring :: (b -> c) -> ((a -> b) -> (a -> c))
as you can see in ring show it returns ((a -> b) -> (a -> c)) and ring show (+1) returns (a -> c)
Related
Considering the type
foo :: a -> ((b -> a) -> c) -> c
I want to create a function that satisfies this type...
I know foo x y = y (\z -> x) satisfies this type as confirmed with :type in GHCi, but how would I get to this final function manually, or step by step?
I also know foo2 f g = \x -> f (g x) would also satisfy foo2 :: (a -> b) -> (c -> a) -> c -> b but don't also know how to get to this function.
It's just a matter of fitting the matching pieces of a puzzle together. The same-named pieces match. The type of foo means it's a function with two parameters:
foo :: a -> ((b -> a) -> c) -> c
-- a f
foo a f = c
-- a :: a
-- f g :: c
-- g b :: a
where
c = f g -- produce a c-type value
g b = a -- define g to produce
-- the value a
f we're given, but g we must invent so that it returns a; fortunately, we're already given an a:
-- f :: ((b -> a) -> c)
-- g
-- g :: b -> a
a is given to us as a parameter of foo, and b is just an unused parameter of g.
Next we can substitute and simplify, using the fact that writing this:
p :: q -> r
p q = r...
is the same as writing this:
p :: q -> r
p = \q -> r...
where we use r... to indicate an expression whose type is r.
Also, s -> t -> r is the same as s -> (t -> r) because, similarly,
h :: s -> t -> r
h s t = r...
h s = (\t -> r...)
h = \s -> (\t -> r...)
all express the same thing.
Your second question can be addressed in the same manner.
x :: a means "the value x has type a"; a :: a means "the value a has type a". The same name a can be used in two different roles; when you're accustomed to it, it can actually be quite a helpful mnemonic.
See also.
An underscore _, or an undefined name beginning with an underscore such as _what, is treated by GHC as a “hole” that you want to fill in. You can use this to ask what type the compiler is expecting, and this can be helpful in figuring out how to iteratively fill in the program. Thankfully, this is a case where it’s very helpful, so I can easily go through it step by step in GHCi (with > indicating the prompt). We begin with a hole foo = _:
> foo :: a -> ((b -> a) -> c) -> c; foo = _
And we receive a message saying Found hole: _ :: a -> ((b -> a) -> c) -> c. GHC suggests foo :: a -> ((b -> a) -> c) -> c as a valid way of filling in the hole, and indeed foo = foo is legal, it’s just not the answer we’re looking for, since it represents an infinite loop.
Instead, we can look at the type and break it down into parts from the top down. We begin with a function type (->) whose input is a and whose output is ((b -> a) -> c) -> c. We can make a function value using a lambda expression, inventing a name for the a value, say x, and put another hole for the body:
> foo :: a -> ((b -> a) -> c) -> c; foo = \ x -> _
…
• Found hole: _ :: ((b -> a) -> c) -> c
…
It now mentions that we have x :: a available to work with, in addition to foo, but this isn’t quite enough, so next we can take apart ((b -> a) -> c) -> c into its input ((b -> a) -> c) and output c. (From now on, for brevity’s sake, I’ll also skip repeating the type signature of foo.)
> foo :: …; foo = \ x -> \ f -> _
…
• Found hole: _ :: c
…
We can’t take apart the type variable c any further, and we know we need to make a value of type c, so we can look at what we have available:
f :: (b -> a) -> c
x :: a
foo :: a -> ((b -> a) -> c) -> c
So our options are:
Recursively call foo
Call f
#1 would quickly put us back in the same situation we’re in, so #2 is all that’s left. f expects a value of type b -> a as an argument:
> foo :: …; foo = \ x -> \ f -> f _
…
• Found hole: _ :: b -> a
…
So again we can write a lambda:
> foo :: …; foo = \ x -> \ f -> f (\ y -> _)
…
• Found hole: _ :: a
…
The only way we can produce a value of the unknown type a is to use the value x :: a that we’ve been given, so the final result is this:
foo = \ x -> \ f -> f (\ y -> x)
And that can be written in exactly the same form as you put in your question, using a little syntactic sugar, and a couple different choices of variable names:
foo = \ x -> \ f -> f (\ y -> x)
foo x = \ f -> f (\ y -> x)
foo x f = f (\ y -> x)
foo x y = y (\ z -> x)
Question 1
foo :: a -> ((b -> a) -> c) -> c
says that foo has to take an a and a function with type (b -> a) -> c and somehow produce a c.
foo a function = c
where a::a and function::(b -> a) -> c
but where can we get the c from?
Good news: function makes cs for us.
Let's use that. function::(b->a) -> c so we can get a c if we give it a (b->a).
So we need to first make a helper function that takes bs and gives us as:
foo a function =
let helper b = a
That's fine! I already had an a so I could use that. We just need to hand function the helper we just made:
foo :: a -> ((b -> a) -> c) -> c
foo a function =
let helper b = a
in function helper
Now notice that helper ignores its input, so we could write
foo :: a -> ((b -> a) -> c) -> c
foo a function =
let helper _ = a
in function helper
And we can use lambda notation for helper:
foo :: a -> ((b -> a) -> c) -> c
foo a function =
let helper = \_ -> a
in function helper
But now we could just write (\_ -> a) instead of helper:
foo :: a -> ((b -> a) -> c) -> c
foo a function =
function (\_ -> a)
And finally, lets abbreviate function as f:
foo :: a -> ((b -> a) -> c) -> c
foo a f = f (\_ -> a)
Question 2
foo2 :: (a -> b) -> (c -> a) -> c -> b
OK, this time we need to make a b. We're given a c and a couple of functions for turning as into bs and cs into as:
foo2 :: (a -> b) -> (c -> a) -> c -> b
foo2
make_b_from_a
make_a_from_c
c
= b
Well, the only thing that can give us a b is make_b_from_a:
foo2 :: (a -> b) -> (c -> a) -> c -> b
foo2
make_b_from_a
make_a_from_c
c
= make_b_from_a a
but now we need an a, but we can use make_a_from_c for that, and we already have a c:
foo2 :: (a -> b) -> (c -> a) -> c -> b
foo2
make_b_from_a
make_a_from_c
c
= make_b_from_a (make_a_from_c c)
Let's shorten the names. I'm going to call the (c->a) one f because we use it before the other one, which I'll call g:
foo2 :: (a -> b) -> (c -> a) -> c -> b
foo2 g f c = g (f c)
We can take the last argument using a lambda:
foo2 :: (a -> b) -> (c -> a) -> c -> b
foo2 g f = \c -> g (f c)
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c)
bind :: Monad m => m a -> (a -> m b) -> m b
-- how do you use >=> to write bind?
I am absolutely so confused, I understand how both of these works but I cant even get started.
I tried all the following alternatives:
bind1 a b = (b a)
bind2 a b = (a >=> b)
bind3 a b = (b >=> a)
bind4 a b = (a b)
but every single attempt raises an error. Where can i possibly start on this question?
Since >>= has 2 parameters, and >=> has 3, how can I use >=> to write >>= when there is 1 less parameter?
First I'd suggest renaming the type parameters so the final result matches:
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c)
bind :: Monad m => m a -> (a -> m c) -> m c
Now we have a b -> m c in the first signature and a -> m c in the second; that suggests renaming also a to b:
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c)
bind :: Monad m => m b -> (b -> m c) -> m c
That leaves the main difference as having an extra argument a. But we evidently don't need that, so we might as well specialize it to the information-less type () (or any other single-value type):
(>=>) :: Monad m => (() -> m b) -> (b -> m c) -> (() -> m c)
bind :: Monad m => m b -> (b -> m c) -> m c
() -> m x is actually isomorphic to m x alone:
addDummyArg :: a -> (() -> a)
addDummyArg c () = c
rmDummyArg :: (() -> a) -> a
rmDummyArg f = f ()
And it's just a matter of using those conversion functions to adapt the functions to each other.
Since >>= has 2 parameters, and >=> has 3, how can I use >=> to write >>= when there is 1 less parameter?
Each function in Haskell has one parameter. You can interpret >=> , as a function that has as first parameter something of type a -> m b and the second something of b -> m c, the a -> m c is the "result" function.
What you here can do is manipulate the first parameter of bind into a function that accepts a parameter, and then provide that parameter, something like:
bind :: Monad m => m a -> (a -> m b) -> m b
bind ma f = (const ma >=> f) undefined
Here with const ma, we thus create a function that takes a parameter we do not care about, then we construct an a -> m c by using >=> and we call it with undefined (or some other value) to produce the m c value.
I'm trying to create a function that composes a function f with a function g that takes multiple arguments.
c :: (a -> b) -> (c -> a) -> c -> b
c x y z = x(y(z))
lift = c c
(lift $ lift $ lift ... c) creates the desired function:
*Main> (lift $ lift $ lift $ lift $ lift $ c) (\x -> x+2) (\x y z a b c -> x*y*z-(a*b*c)) 1 2 3 4 5 6
-112
However, when I attempt to define a function to produce a function that takes f, g, then n arguments (to save typing), the following error occurs:
cn 1 = c
cn k = lift (cn(k-1))
<interactive>:9:1: error:
* Occurs check: cannot construct the infinite type: a ~ c0 -> a
Expected type: t -> (a -> b) -> a -> b
Actual type: t -> (a -> b) -> (c0 -> a) -> c0 -> b
* Relevant bindings include
cn :: t -> (a -> b) -> a -> b (bound at <interactive>:9:1)
Why does this error occur, and how might I resolve it?
You cannot make polyvariadic functions in Haskell without typeclasses.
When you try to make a function that takes either one or two arguments, you try to make a function of type a -> b and a -> p -> b. Hence, the compiler must infer that the type b is equivalent to p -> b, so the type of the function becomes a -> p -> p -> p -> .... In other words, an infinite type.
A similar problem occurs when you try to make this function. The first line is fine:
cn 1 = c
This would imply something like cn :: Int -> (b -> c) -> (a -> b) -> a -> c. However, we now have a problem in the second line:
cn k = lift (cn (k-1))
Since we know that cn :: Int -> (b -> c) -> (a -> b) -> a -> c, we must infer that cn (k-1) :: (b -> c) -> (a -> b) -> a -> c. However, since lift :: (x -> y -> z) -> x -> (w -> y) -> w -> z, we see that the return value must be of type (b -> c) -> (w -> a -> b) -> w -> c, which clashes with the original type declaration.
TL;DR: you can't change the type of a Haskell function/value via values. This means you can't write polyvariadic functions without certain tricks.
Why does the following typecheck?
cancel x y = x
distribute f g x = f x (g x)
identity = distribute cancel cancel
Clearly cancel :: a -> b -> a, distribute :: (a -> b -> c) -> (a -> b) -> a -> c and identity :: a -> a. Now, distribute cancel :: (a -> b) -> a -> a, but I don't understand why cancel matches with a -> b.
Could anyone explain this to me?
Let's make all the type variables distinct:
identity = distribute cancel1 cancel2
where distribute :: (a -> b -> c) -> (a -> b) -> a -> c
cancel1 :: x -> y -> x
cancel2 :: r -> s -> r
So, simply lining up the types we need to unify to prove that distribute call checks out:
distribute :: (a -> b -> c) -> (a -> b) -> a -> c
cancel1 :: x -> y -> x
cancel2 :: r -> s -> r
cancel1 is obvious; we have:
a ~ x
b ~ y
c ~ x
(The ~ sign is basically how we write equality of types in Haskell; you can use it in actual code if you turn on some extensions)
Let's substitute those in
distribute :: (x -> y -> x) -> (x -> y) -> x -> x
cancel1 :: x -> y -> x
cancel2 :: r -> s -> r
For the next bit, we need to remember that the arrow is a binary operator. It takes exactly two parameters: an argument type and a result type.So if we've got a function type with two arrows one of them must be inside the argument type or result type of the other. In a case like r -> s -> r, we're using the right associativity of -> to leave out parentheses that would make it obvious: it's really r -> (s -> r).1
So then:
distribute :: (x -> y -> x) -> (x -> y ) -> x -> x
cancel1 :: x -> y -> x
cancel2 :: r -> (s -> r)
So now we can immediately read off:
x ~ r
y ~ s -> r
More substitution:
distribute :: (r -> (s -> r) -> r) -> (r -> (s -> r)) -> r -> r
cancel1 :: r -> (s -> r) -> r
cancel2 :: r -> (s -> r)
So the thing that cancel1 is ignoring is a function of type s -> r, which is also what cancel2 returns. Remembering the f x (g x) implementation of distribute, this makes sense. cancel1 and cancel2 both have to be called with the same thing; cancel1 then receives the result of calling cancel2 as its second argument, which it promptly ignores, so it doesn't matter what the type of cancel2's second parameter is as it's never actually called on another argument (any function at all that accepts r as its first parameter would have worked here). This is all an elaborate way to write a function that does nothing: identity.
1 If you have trouble remembering whether -> is right or left associative, you may have heard that all Haskell functions take a single argument and we commonly "fake" multiple-argument functions by using functions that return other functions. That's what's going on here, and why the function arrow associates to the right.
cancel has type a -> b -> a, but that's the same as a -> (b -> a), so it's a function type with a input and b -> a output.
a -> b matches any function type whatsoever; in this case, a matches a and b matches b -> a.
distribute cancel (\a b c -> a) checks out similarly. Haskell functions are curried, so there's always just a single input type and a single return type, but the return type can also be a function.
I have too functions:
higherOrderPure :: (a -> b) -> c
effectful :: Monad m => (a -> m b)
I'd like to apply the first function to the second:
higherOrderPure `someOp` effectful :: Monad m => m c
where
someOp :: Monad m => ((a -> b) -> c) -> (a -> m b) -> m c
Example:
curve :: (Double -> Double) -> Dia Any
curve f = fromVertices $ map p2 [(x, f x) | x <- [1..100]]
func :: Double -> Either String Double
func _ = Left "Parse error" -- in other cases this func can be a useful arithmetic computation as a Right value
someOp :: ((Double -> Double) -> Dia Any) -> (Double -> Either String Double) -> Either String (Dia Any)
someOp = ???
curve `someOp` func :: Either String (Dia Any)
The type
Monad m => ((a -> b) -> c) -> (a -> m b) -> m c
is not inhabited, i.e., there is no term t having that type (unless you exploit divergence, e.g. infinite recursion, error, undefined, etc.).
This means, unfortunately, that it is impossible to implement the operator someOp.
Proof
To prove that it is impossible to construct such a t, we proceed by contradiction.
Assume t exists with type
t :: Monad m => ((a -> b) -> c) -> (a -> m b) -> m c
Now, specialize c to (a -> b). We obtain
t :: Monad m => ((a -> b) -> a -> b) -> (a -> m b) -> m (a -> b)
Hence
t id :: Monad m => (a -> m b) -> m (a -> b)
Then, specialize the monad m to the continuation monad (* -> r) -> r
t id :: (a -> (b -> r) -> r) -> ((a -> b) -> r) -> r
Further specialize r to a
t id :: (a -> (b -> a) -> a) -> ((a -> b) -> a) -> a
So, we obtain
t id const :: ((a -> b) -> a) -> a
Finally, by the Curry-Howard isomorphism, we deduce that the following is an intuitionistic tautology:
((A -> B) -> A) -> A
But the above is the well-known Peirce's law, which is not provable in intuitionistic logic. Hence we obtain a contradiction.
Conclusion
The above proves that t can not be implemented in a general way, i.e., working in any monad. In a specific monad this may still be possible.
I think you can achieve what you want by writing a monadic version of curve:
curveM :: Monad m => (Double -> m Double) -> m (QDiagram B R2 Any)
curveM f = do
let xs = [1..100]
ys <- mapM f xs
let pts = map p2 $ zip xs ys
return $ fromVertices pts
This can easily be written shorter, but it has the type you want. This is analogous to map -> mapM and zipWith -> zipWithM. The monadic versions of the functions have to be separated out into different implementations.
To test:
func1, func2 :: Double -> Either String Double
func1 x = if x < 1000 then Right x else Left "Too large"
func2 x = if x < 10 then Right x else Left "Too large"
> curveM func1
Right (_ :: QDiagram B R2 Any)
> curveM func2
Left "Too large"