Understanding the signature of <$> - haskell

I have the applicative <$> operator more or less figured out, but I can't understand the signature I'm getting with the following example:
ghci> let f x y z = x + y + z -- f::Num a => a -> a -> a -> a
ghci> f <$> Just 2 <*> Just 3 <*> Just 4
Just 9
This result I understand, but when checking the following type:
ghci> :t (<$> f)
(<$> f) :: Num a => ((a -> a -> a) -> b) -> a -> b --This makes no sense to me
That signature I would understand as : a function that takes a (a -> a- > a) -> b function and an a as parameters and returns a b. According to this reasoning , I should call this like :
(<$>f) f 4
which would result in an Integer.
Obviously this is not true, so can you please help me understand how to read the type of (<$> f)?

a function that takes a (a -> a- > a) -> b function and an a as parameters and returns a b.
This is correct.
According to this reasoning , I should call this like :
(<$>f) f 4
which would result in an Integer.
No, because f does not have type (a -> a -> a) -> b or one compatible with it. Instead it has type Num a => a -> a -> a -> a. That is, f takes three numbers and produces a number, whereas we're looking for a function that takes a function (of type a -> a -> a) as its first argument.

<$> takes as a second argument something of type g b, where g is any applicative functor.
You are passing f :: Num a => a -> a -> a -> a as a second argument. Let's ignore the Num a context to keep things simple.
Hence, we look for g,b such that g b = a -> a -> a -> a.
Let's write the type of f in prefix form:
f :: (->) a ((->) a ((->) a a)) = g b
Hence, g = (->) a and b = ((->) a ((->) a a)). The latter is b = a -> a -> a in infix form.
It happens that (->) a is an applicative functor, so <$> f type checks. Note however that <$> is used on a completely different functor than the Maybe one you were using in your examples. Hence the confusion.
TL;DR: overloaded identifiers can shapeshift to many things adapting to their contexts, possibly in some unexpected way.

Related

Explanation of <$> and <*> when used with functions

I am learning haskell currently and I am having a really hard time wrapping my head around how to explain <$> and <*>'s behavior.
For some context this all came from searching how to use an or operation when using takeWhile and the answer I found was this
takeWhile ((||) <$> isDigit <*> (=='.'))
In most of the documentation I have seen, <*> is used with a container type.
show <*> Maybe 10
By looking at
(<$>) :: Functor f => (a -> b) -> f a -> f b
It tells me that <*> keeps the outer container if its contents and applies the right to the inside, then wraps it back into the container
a b f a f b
([Int] -> String) -> [Just]([Int]) -> [Just]([String])
This makes sense to me, in my mind the f a is essentially happening inside the container, but when I try the same logic, I can make sense to me but I cant correlate the logic
f = (+) <$> (read)
so for f it becomes
a b f a f b
([Int] -> [Int -> Int]) -> ([String] -> [Int]) -> ([String] -> [Int -> Int])
So f being the container really confuses me when I try and work out what this code is going to do. I understand when I write it out like this, I can work it out and see its basically equivalent to the .
(.) :: (b -> c) -> (a -> b) -> a -> c
b c a b a c
([Int] -> [Int -> Int]) -> ([String] -> [Int]) -> ([String] -> [Int -> Int])
so it can be written as
f = (+) . read
Why not just write it as just that? Why wasn't the original snippet just written as
takeWhile ((||) . isDigit <*> (=='.'))
or does <$> imply something in this context that . des not?
Now looking at <*>, it seems like it is basicly exactly the same as the <$> except it takes two containers, uses the inner of both, then puts it pack in the container
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
so
Just show <*> Just 10
f a b f a f b
[Just]([Int->Int]->[Int]) -> [Just]([Int->Int]) -> [Just]([Int])
However with functions, it becomes murky how things are being passed around to each other.
Looking at the original snippit and breaking it up
f1 :: Char -> Bool -> Bool
f1 = (||) . isDigit
f2 :: Char -> Bool
f2 = f1 <*> (== '.')
<*> behavior in f2 is
f a b f a f b
([Char] -> [Bool] -> [Bool]) -> ([Char] -> [Bool]) -> ([Char] -> [Bool])
So using previous logic, I see it as Char -> is the container, but its not very useful for me when working out what's happening.
It looks to me as if <*> is passing the function parameter into right side, then passing the same function parameter, and the return value into the left?
So to me, it looks equivalent to
f2 :: Char -> Bool
f2 x = f1 x (x=='_')
Its a bit of mental gymnastics for me to work out where the data is flowing when I see <*> and <$>. I guess im just looking for how an experienced haskell-er would read these operations in their head.
The applicative instance for functions is quite simple:
f <*> g = \x -> f x (g x)
You can verify for yourself that the types match up. And as you said,
(<$>) = (.)
(Ignoring fixity)
So you can rewrite your function:
(||) <$> isDigit <*> (=='.')
(||) . isDigit <*> (=='.')
\x -> ((||) . isDigit) x ((=='.') x)
-- Which can simply be rewritten as:
\x -> isDigit x || x == '.'
But it's important to understand why the function instance is as it is and how it works. Let's begin with Maybe:
instance Applicative Maybe where
pure :: a -> Maybe a
pure x = Just x
(<*>) :: Maybe (a -> b) -> Maybe a -> Maybe b
Nothing <*> _ = Nothing
_ <*> Nothing = Nothing
(Just f) <*> (Just x) = Just (f x)
Ignore the implementation here and just look at the types. First, notice that we've made Maybe an instance of Applicative. What exactly is Maybe? You might say that it's a type, but that isn't true - I can't write something like
x :: Maybe
- that doesn't make sense. Instead, I need to write
x :: Maybe Int
-- Or
x :: Maybe Char
or any other type after Maybe. So we give Maybe a type like Int or Char, and it suddenly becomes a type itself! That's why Maybe is what's known as a type constructor.
And that's exactly what the Applicative typeclass expects - a type constructor, which you can put any other type inside. So, using your analogy, we can think of giving Applicative a container type.
Now, what do I mean by
a -> b
?
We can rewrite it using prefix notation (the same way 1 + 2 = (+) 1 2)
(->) a b
And here we see that the arrow (->) itself is also just a type constructor - but unlike Maybe, it takes two types. But Applicative only wants a type constructor which takes one type. So we give it this:
instance Applicative ((->) r)
Which means that for any r, (->) r is an Applicative. Continuing the container analogy, (->) r is now a container for any type b such that the resulting type is r -> b. What that means is that the contained type is actually the future result of the function on giving it an r.
Now for the actual instance:
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
Substituting (->) r as the applicative,
(<*>) :: ((->) r (a -> b)) -> ((->) r a) ((->) r b)
-- Rewriting it in infix notation:
(<*>) :: (r -> (a -> b)) -> (r -> a) -> (r -> b)
How would we go about writing the instance? Well, we need a way to get the contained type out of the container - but we can't use pattern matching like we did with Maybe. So, we use a lambda:
(f :: r -> (a -> b)) <*> (g :: r -> a) = \(x :: r) -> f x (g x)
And the type of f x (g x) is b, so the entire lambda has type r -> b, which is exactly what we were looking for!
EDIT: I noticed that I didn't talk about the implementation of pure for functions - I could update the answer, but try seeing if you can use the type signature to work it out yourself!

Haskell function with type (num -> num) -> num

I am struggling with an exercise in R. Bird's functional programming book that asks for an example of a function with type (num -> num) -> num
The best I can come up with is a polymorphic type
func1 f = f 3
:t func1
func1 :: Num t1 => (t1 -> t2) -> t2
The problem I am having is that I can't specify the return type of f, so the type remains (num -> t2) -> t2.
My attempt to force the return type of f is as follows:
square x = x * x
:t func1 square
func1 square :: Num t2 => t2 -> t2
Because of course if I try to find the type of func1 ∘ square it will just be num -> num
If it is enough to give a function which can be assigned that type, then yours is already enough. That is, the following type-checks just fine:
func1 :: Num a => (a -> a) -> a
func1 f = f 3
If, on the other hand, you want a function which is inferred to have that type, then you need to do some trickery. What we want to do here is to specify that the result of f 3 and the 3 that we fed in have the same type. The standard way to force two terms to have the same type is to use asTypeOf, which is implemented this way:
asTypeOf :: a -> a -> a
asTypeOf x _ = x
So let's try:
> :t \f -> f 3 `asTypeOf` 3
(Num a, Num t) => (t -> a) -> a
Unfortunately for us, this doesn't work, because the 3 in f 3 and the standalone 3 are inferred to be using potentially different instances of Num. Still, it is a bit closer than \f -> f 3 was -- note the new Num a constraint on the output that we didn't have before. An obvious next idea is to let-bind a variable to 3 and reuse that variable as the argument to both f and asTypeOf; surely then GHC will get the picture that f's argument and result have the same type, right?
> :t \f -> let x = 3 in f x `asTypeOf` x
(Num a, Num t) => (t -> a) -> a
Drat. Turns out that lets do what's called "let generalization"; the x will be just as polymorphic as the 3 was, and can be specialized to different types at different use sites. Usually this is a nice feature, but because we're doing an unnatural exercise we need to do unnatural things...
Okay, next idea: some lambda calculi do not include a let, and when you need one, instead of writing let a = b in c, you write (\a -> c) b. This is especially interesting for us because Haskell uses a specially-restricted kind of polymorphism that means that inside c, the type of a is monomorphic. So:
> :t \f -> (\x -> f x `asTypeOf` x) 3
Num a => (a -> a) -> a
And now you complain that asTypeOf is cheating, because it uses a type declaration that doesn't match its inferred type, and the whole point of the exercise was to get the right type through inference alone. (If we were okay with using type declarations that don't match the inferred type, we could have stopped at func1 :: Num a => (a -> a) -> a; func1 f = f 3 from way back at the beginning!) Okay, no problem: there's another standardish way to force the types of two expressions to unify, namely, by putting them in a list together. So:
> :t \f -> (\x -> head [f x, x]) 3
Num a => (a -> a) -> a
Phew, now we're finally at a place where we could in principle build, from the ground up, all the tools needed to get a term of the right type without any type declarations.
func1 f = let x = f x in x This is a partial function, it technically has the type you want and you should be aware of what they are and how they work in haskell.

What is the difference between typevariable a and b

I am learning haskell and one of the tricky part are type variables.
Consider following example:
Prelude> :t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
there is type variables a and b, they can be any type. And f is a type that has to be implemented a Functor.
Lets define a function for first argument for fmap:
Prelude> let replaceWithP = const 'p'
Now, I pass the function replaceWithP to fmap and looking at the type signature:
Prelude> :t fmap replaceWithP
fmap replaceWithP :: Functor f => f b -> f Char
Why does f a becomes to f b, why does it not stay a?
First, the type
fmap replaceWithP :: Functor f => f b -> f Char
is exactly equivalent to
fmap replaceWithP :: Functor f => f a -> f Char
because all type variables are implicitly universally quantified, so they can be renamed at will (this is known as alpha-conversion).
One might still wonder where the name b printed by GHC comes from. After all, fmap had f a in its type, so why did GHC choose to rename it as b?
The "culprit" here is replaceWithP
> :t const
const :: a -> b -> a
> let replaceWithP = const 'p'
> :t replaceWithP
replaceWithP :: b -> Char
So, b comes from the type of replaceWithP.
Type variables can be thought of normal variables, except you have types instead.
What does this mean? For instance, the variable a in C might be defined as:
int a = 2;
What are the possible values that you could have assigned a? The whole int range, because that's the set of values that a may take on. Let's take a look at this in pseudo-Haskell:
type b = Int
What are the set of values that b may take on? That's a trickier question. Typically we're used to seeing things such as 2, "hello", or True as values. However, in Haskell, we also allow types to be treated as values. Sort of. Let's say that b can take on any kind of form *. Essentially, this includes all types that do not need extra information for their construction:
data Tree a = Leaf a | Branch (Tree a) (Tree a)
Tree -- no, has kind: * -> *
Tree Int -- okay!
Int -- okay!
String -- okay!
This means that in your example:
fmap :: Functor f => (a -> b) -> f a -> f b
The variables a and b can be thought of variables that can take on types of any form provided that the type you decide to give it is within the appropriate range of type values (as restricted by kinds).
To more precisely answer your question now: why do we observe that:
fmap :: Functor f => (a -> b) -> f a -> f b
fmap replaceWithP :: Functor f => f b -> f Char
Let me rewrite the following equivalent definition, because variable naming can cause confusion:
fmap :: Functor f => (a -> b) -> f a -> f b
fmap replaceWithP :: Functor f => f z -> f Char
Hopefully this looks more clear now. When you supplied the replaceWithP :: x -> Char function, the following mappings occur:
-- Function types
fmap :: Functor f => (a -> b) -> f a -> f b
replaceWithP :: x -> Char
-- Type variable mappings
a -> x
b -> Char
What does this look like if we perform substitution?
Functor f => (x -> Char) -> f x -> f Char
After you have supplied in the replaceWithP function, you consume the first parameter, so you're left with:
fmap replaceWithP :: Functor f => f x -> f Char
Or equivalently:
fmap replaceWithP :: Functor f => f b -> f Char

How can I apply an arbitrary function under an existential wrapper?

I'm trying to write a function (called hide here), which can apply a sufficiently polymorphic function inside an existential wrapper (or lift functions to work on wrappers with hidden types; hence "hide"):
{-# LANGUAGE GADTs
, RankNTypes
#-}
data Some f
where Some :: f a -> Some f
hide :: (forall a. f a -> g b) -> Some f -> Some g
hide f (Some x) = Some (f x)
data Phantom a = Phantom
cast :: Phantom a -> Phantom b
cast Phantom = Phantom
works :: Some Phantom -> Some Phantom
works = hide cast
doesn't :: Functor f => Some f -> Some f
doesn't = hide (fmap $ \x -> [x])
{-
foo.hs:23:17:
Couldn't match type ‘b0’ with ‘[a]’
because type variable ‘a’ would escape its scope
This (rigid, skolem) type variable is bound by
a type expected by the context: f a -> f b0
at foo.hs:23:11-33
Expected type: f a -> f b0
Actual type: f a -> f [a]
In the first argument of ‘hide’, namely ‘(fmap $ \ x -> [x])’
In the expression: hide (fmap $ \ x -> [x])
In an equation for ‘doesn't’: doesn't = hide (fmap $ \ x -> [x])
Failed, modules loaded: none.
-}
but :: Functor f => Some f -> Some f
but = hide' (fmap $ \x -> [x])
where hide' :: (forall a. f a -> g [a]) -> Some f -> Some g
hide' f (Some x) = Some (f x)
So I pretty much understand why this is happening; works shows that hide does in fact work when the return type is completely unrelated to the input type, but in doesn't I'm calling hide with an argument of type a -> [a]. hide is supposed to get to "choose" the type a (RankNTypes), but b is ordinarily polymorphic. When b in fact depends on a, a could leak out.
But in the context where I'm actually calling it, a doesn't in fact leak out; I immediately wrap it up in Some. And in fact I can write an alternate hide' that accepts specifically a -> [a] functions and works with the exact same implementation, just a different type signature.
Is there any way I can type the implementation hide f (Some x) = Some (f x) so that it works more generally? Really I'm interested in lifting functions with type a -> q a, where q is some arbitrary type function; i.e. I expect the return type to depend on a, but I don't care how it does so. There probably are use cases where q a is a constant (i.e. the return type doesn't depend on a), but I imagine they'll be much rarer.
This example is pretty silly, obviously. In my real use case I have a GADT Schema a that roughly speaking represents types in an external type system; the phantom parameter gives a Haskell type that could be used to represent values in the external type system. I need that phantom parameter to keep everything type safe, but sometimes I construct Schemas based on runtime data, in which case I don't know what that parameter type is.
So I appear to need another type which is agnostic about the type parameter. Rather than make (yet) another parallel type, I was hoping to use a simple existential wrapper like Some to construct it from Schema, and be able to lift functions of type forall a. Schema a -> Schema b to Some Schema -> Some Schema. So if I have an XY problem and I'd be better of using some other means of passing around Schema a for unknown a, that would also solve my problem.
As David Young says, you can write
hide' :: (forall a. f a -> g (q a)) -> Some f -> Some g
hide' f (Some x) = Some (f x)
does :: Functor f => Some f -> Some f
does = hide' (fmap (:[]))
but instead of making hide fmap-like, you can make it bind-like:
hide'' :: (forall a. f a -> Some g) -> Some f -> Some g
hide'' f (Some x) = f x
does :: Functor f => Some f -> Some f
does = hide'' (Some . fmap (:[]))
But this is a bit boilerplateable.
Or, more generally
elim :: (forall a. f a -> c) -> Some f -> c
elim f (Some x) = f x
I'm not sure how useful this is for your larger use-case as you'd have to refactor all your existing operations to use continuation passing style, but continuations can be used to implement a hide that works for both of your examples and keeps b completely generic.
hide :: (forall r a. f a -> (forall b. g b -> r g) -> r g) -> Some f -> Some g
hide f (Some x) = f x Some
cast :: Phantom a -> (forall b. Phantom b -> r Phantom) -> r Phantom
cast Phantom f = f Phantom
works :: Some Phantom -> Some Phantom
works = hide cast
alsoWorks :: Functor f => Some f -> Some f
alsoWorks = hide (\a f -> f $ fmap (\x -> [x]) a)
You can make it somewhat nicer by factoring out the CPS-conversion which allows you to more easily use existing functions like your original cast:
hide :: (forall r a. f a -> (forall b. g b -> r g) -> r g) -> Some f -> Some g
hide f (Some x) = f x Some
cps :: (f a -> g b) -> (f a -> (forall c. g c -> r) -> r)
cps f a c = c (f a)
cast :: Phantom a -> Phantom b
cast Phantom = Phantom
works :: Some Phantom -> Some Phantom
works = hide $ cps cast
alsoWorks :: Functor f => Some f -> Some f
alsoWorks = hide $ cps $ fmap (\x -> [x])

need to know what <*> <$> and . do in haskell

What are these operators doing?
(.) :: (b -> c) -> (a -> b) -> a -> c
(<$>) :: Functor f => (a -> b) -> f a -> f b
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
I don't have any idea when I see the signatures. Perhaps some example with a simple and easy to understand explanation will help me.
I am also learning Haskell, and my recommendation is to have a look into Learn You a Haskell for Great Good!, and more precisely:
for (.) read Function composition
for <$> and <*> read Applicative functors
In essence:
(.) is function composition: if you have g :: a -> b and f :: b -> c then f . g is essentially f(g(x)): first use g on an a to get a b and then use f on that b to get a c
<$> takes a function taking an a and returning a b, and a functor that contains an a, and it returns a functor that contains a b. So <$> is the same as fmap :: (a -> b) -> f a -> f b
<*> takes a functor that contains a function taking an a and returning a b, and a functor that contains an a, and it returns a functor that contains a b. So <*> kind of extract the function from a functor and applies it to an arguments also inside a functor, and finally returns the result into a functor
Note the explanations that you find in the book chapters are better than my attempt above
Maybe you learn via examples (like I do), so here are some simple ones you can mess around with in GHCI.
(.) - Function Composition
-- (.) :: (b -> c) -> (a -> b) -> a -> c
> f = (+1)
> g = (*2)
> a = f . g
> a 0
1 -- f( g( 0 ) ) or (0 * 2) + 1
> b = g . f
> b 0
2 -- g( f( 0 ) ) or (0 + 1) * 2
<$> - Functor
-- (<$>) :: Functor f => (a -> b) -> f a -> f b
> a = (*2)
> b = Just 4
> a <$> b
Just 8
<*> - Applicative
-- (<*>) :: Applicative f => f (a -> b) -> f a -> f b
> a = Just (*2)
> b = Just 4
> a <*> b
Just 8
I hope that helps.
The (.) operator composes functions. For example, \x -> f (g x) is the same as f . g. You can do this for arbitrary functions, e.g. \x -> f (g (h x)) equals f . g . h.
The <$> and <*> operators are not defined in terms of functionality. Their functionality depends on the actual type f that they are applied on. The <$> operator is an alternative for the fmap function in the Functor library. For example, for the Maybe type it takes the left operand and only applies it if the right operand is a Just value. So in order to find out what these operators do, just have a look at the implementations for the specific types.
I'm a a newbie to Haskell and sometimes Haskell type declarations confuse me, too.
It's easy to get lost at first because the tutorial says that the Capitalization naming convention is usually for type declaration and the camelCase naming convention is usually for variable.
Actually, this belongs to a higher technique in Haskell, may be polymorphism. Just think of f, a and b as some kind type variables - variables that handle type. And class in Haskell is not for Object like OOP but for type. So Functor f means that type f belongs to class Functor and so on.
If you replace these letter a, b, c with some type - called instance - for example String Int Char. It will make sense:
(.) :: (Int -> Char) -> (String -> Int) -> String -> Char
(<$>) :: Functor Maybe => (String -> Int) -> Maybe String -> Maybe Int -- type `Maybe` belongs to class `Functor`
...
While the common uses of <$> and <*> is obscured by the fact that they are in a typeclass, you can usually read the haddock documentation for this information. Use Hoogle if you have a hard time finding to which module a function belongs.

Resources