In Haskell we can write code like this:
// (<*>) :: Applicative f => f (a -> b) -> f a -> f b
// const :: a -> b -> a
// id :: b -> b
let id = const <*> const
How to do same thing in F#?
I try write code something like this, but it isn't same
let ( <*> ) f v =
match v with
| Some v' ->
match f with
| Some f' -> Some (f' v')
| _ -> None
| _ -> None
let cnst a _ = a
let id = cnst <*> cnst // but it seems impossible
let id' x = (Some (cnst x)) <*> (Some(cnst x x)) // it works
But in Haskell id::b->b
, in F# id:'a->'a Option
What I do wrong? How to achieve the same result?
PS: As I know with an Applicative, our values are wrapped in a context, just like Functors and functions are wrapped in a context too!
Some((+)3) and Some(2)
In this case Context is Option
And Applay
method is like this:
let Apply funInContext valInContext =
match funInContext with // unwrap function
| Some f ->
match valInContext with // unwrap value
| Some v -> Some(f v) // applay function on value and wrap it
| _ -> None
| _ -> None
I'm slightly confused by what your code is trying to achieve because it has the type
(a -> Maybe b) -> Maybe a -> Maybe b
This is the type of bind for the monad structure we usually imbue Maybe
/option
with but it doesn't make sense if you're trying to work with the applicative instance for functions that we have in Haskell. There are two things we need to change then, the first is that we need to work with functions and applicatives in order to have the code achieve the desired effect. That ought to have the type
(a -> (b -> c)) -> (a -> b) -> (a -> c)
So we can write this as
let ( <*> ) f x a = (f a) (x a)
Now if we step the original example
(cnst <*> cnst) a = (cnst a) (cnst a)
= a
so we indeed have that cnst <*> cnst = id
as required.