Do function type parameter labels matter - f#

I'm teaching myself F#. My question comes from my attempts to solve exercise 2.13 in the book 'Functional Programming Using F#', which asks me to define a function curry as:
curry : ('a * 'b -> 'c) -> 'a -> 'b -> 'c
My current result is
curry : f:('a * b' -> 'c) -> x:'a -> y:'b -> 'c
Question
Do the parameter labels matter? Is my solution correct, or does the correct solution not have the labels f:, x: , and y:?

No, the parameter labels don't matter for the solution to this exercise, which is why they were left out of the expected solution. A function defined as let curry f x y = ... and a function defined as let curry funcToCurry firstParam secondParam = ... would both be valid solutions, as long as they did the right thing. What matters in this exercise is the shape of the resulting function (that is, the types that it takes and returns), not the names you gave its parameter(s).

From a functional perspective (as-in, how it works, not as-in functional programming), the thing that matters is whether or not they are equivalent. The way to test this is to see if the two are interchangeable.
Lets pretend you defined your function like this (notice the type signature matches yours):
let curry f x y =
f(x,y);;
val curry : f:('a * 'b -> 'c) -> x:'a -> y:'b -> 'c
Then, lets define a second function which takes a function of the desired type signature like this:
let makeCurried (f: ('a * 'b -> 'c)->'a->'b->'c) g : ('a -> 'b -> 'c) = f g;;
val makeCurried :
f:(('a * 'b -> 'c) -> 'a -> 'b -> 'c) ->
g:('a * 'b -> 'c) -> ('a -> 'b -> 'c)
Notice that the first parameter of makeCurried takes a function of type ('a * 'b -> 'c) -> 'a -> 'b -> 'c.
Now the test is: can you pass the curry function to makeCurried for the first parameter? If so, then the two are equivalent.
makeCurried curry (fun (x,y)->x*y);;
val it : (int -> int -> int) = <fun:it#7>
Yes! So the annotations on the type signature don't matter since the type signatures are equivalent.

Related

F# Simple Signature

I found similar things, but not exactly what i'm looking for
Why does
let map x f = f x
return
val map : 'a -> ('a -> 'b) -> 'b
and
let rec merge f xs a =
match xs with
| [] -> a
| y::ys -> f y (merge f ys a);;
return
val merge : f:('a -> 'b -> 'b) -> xs:'a list -> a:'b -> 'b
and
let rec merge2 a = function
| [] -> a
| x::xs -> fold f (f a x) xs;;
returns
val merge2: f:('a -> 'b -> 'a) -> a:'a -> _arg1:'b list -> 'a
Thank you for the clarification.
Ok I'll show you the first one then you can check the others.
Notice how you do f x this means that f is a function (that always has signature 'a -> 'b for some 'a and 'b.
Now as x is the argument to f it must have the same type as the input to f which I named 'a here.
Now the result of f x is of course of type 'b
Now put it all together:
map takes two arguments:
x : 'a
and f : 'a -> 'b
and has result-type 'b
so it has signature map : 'a -> ('a -> 'b) ->b`
Here is the same argument for your
let rec merge f xs a =
match xs with
| [] -> a
| y::ys -> f y (merge f ys a);;
first look at the first case of the match:
it matches an empty list so xs much be a list of some type 'a: xs : 'a list
it returns a which has some unknown type 'b which is also the result of the match and therefore merge itself!
now to the second line:
As xs had type 'a list now you must have
y : 'a
ys : 'a list
therefore you plug in a 'a and then a 'b into f and return it's result to the match and merge (which, as we have seen, has return-type 'b)
You now see, that f must have type f : 'a -> 'b -> 'b and you are again done if you assemble the type of merge
side-note
remember how I claimed that every function has signature 'a -> 'b for some types and now I write stuff like 'a -> 'b -> 'b?
This is indeed consistent if you read the last as 'a -> ('b -> 'b) which is of course just what we call currying: you don't need functions with multiple arguments if you can just return functions and as long as you don't look to deep into the produced IL you should think of F# doing exactly this ;)
I think you will manage the last one yourself - try it, if you have problems edit your question to indicate your problem and we gonna help ;)

type inference of (>>)(>>) (function composition)

I have seen somewhere (sorry, I can't find the a reference) this operator composition:
(>>)(>>)
where (>>): (('a -> 'b) -> ('b -> 'c) -> 'a -> 'c) - (>>) is the function composition operator.
I find simpler examples are easy to understand. For example (>>)f, where f: i -> i.
(>>)(i -> i) becomes (i -> 't) -> i -> 't. This is because ('a -> 'b) is curried away, 'b is inferred to be i and 't remains a generic type.
I do not fully understand (>>)(>>):
The use
What would (>>)(>>) and (<<)(<<) used for?
Why it is necessary to make the argument explicit?
> (>>)(>>);;
(>>)(>>);;
-^^^^^^
C:\Users\...\Temp\stdin(3,2): error FS0030: Value restriction. The value 'it' has been inferred to have generic type
val it : (((('_a -> '_b) -> '_c -> '_b) -> '_d) -> ('_c -> '_a) -> '_d)
Either make the arguments to 'it' explicit or, if you do not intend for it to be generic, add a type annotation.
As suggested by the error message:
> let strangeFun arg = (>>)(>>) arg;;
val strangeFun : arg:((('a -> 'b) -> 'c -> 'b) -> 'd) -> (('c -> 'a) -> 'd)
There have been several explanations of value restriction around here in the past; here is one I wrote that explains why it is necessary. For completeness I'll copy here the example code that would be incorrect if the value restriction was removed:
let f : 'a -> 'a option =
let r = ref None
fun x ->
let old = !r
r := Some x
old
f 3 // r := Some 3; returns None : int option
f "t" // r := Some "t"; returns Some 3 : string option!!!
As far as what (>>)(>>) would be used for, I admit I don't know. There is however a similar-looking but useful function, which is (<<) << (<<) (better known in Haskell as (.).(.)), which returns a similar composition operator whose second and returned functions can take two arguments instead of one.
let (<<<<) f = ((<<) << (<<)) f;;
// val ( <<<< ) : f:('a -> 'b) -> (('c -> 'd -> 'a) -> 'c -> 'd -> 'b)

Built in f# operator to compose functions with the same input but different outputs?

I understand the << compose operator takes two functions that both take in and return the same type. e.g. (lhs:'a -> 'a) -> (rhs:'a -> 'a) -> 'a
I often find myself wanting something like (lhs:'a -> 'b) -> (rhs:'c -> 'b) -> 'b in cases where I'm interested in side affects and not the return value 'b is probably the unit type. This is only when I have two lines in succession where I'm persisting something to a database.
Is there a built in function or idiomatic F# way of doing this without writing something like
let myCompose lhs rhs arg =
lhs arg
rhs arg
Backward composition operator (<<) is defined as:
( << ) : ('b -> 'c) -> ('a -> 'b) -> 'a -> 'c`
With two predicates applied, it is actually a function that takes initial value of 'a returning 'c, while the value of 'b is processed inside.
From the code sample you provided, let me assume that you need applying an argument to both predicates. There are several ways to do this:
Discarding the value returned by the (first) predicate, returning the original argument instead. Such operator exists in WebSharper:
let ( |>! ) x f = f x; x
// Usage:
let ret =
x
|>! f1
|>! f2
|> f3
I like this approach because:
it does not complicate things; each function application is atomic, and the code appears more readable;
it allows chaining throughout three or more predicates, like in the example above;
In this case, f must return unit, but you can easily work this around:
let ( |>!! ) x f = ignore(f x); x
Applying the argument to both predicates, returning a tuple of results, exactly as in your own example. There's such operator OCaml, easy to adapt to F#:
val (&&&) : ('a -> 'b) -> ('a -> 'c) -> 'a -> 'b * 'c
As #JackP noticed, &&& is already defined in F# for another purpose, so let's use another name:
/// Applying two functions to the same argument.
let (.&.) f g x = (f x, g x)
// Usage
let ret1, ret2 =
x
|> (f .&. g)
Note The samples above are for straight order of function application. If you need them applied in a reverse order, you need to modify the code accordingly.
The backward or reverse composition operator (<<) does not take two functions that both take in and return the same type; the only constraint is that the output type of the first function to be applied must be the same as the input type of the function it's being composed into. According to MSDN, the function signature is:
// Signature:
( << ) : ('T2 -> 'T3) -> ('T1 -> 'T2) -> 'T1 -> 'T3
// Usage:
func2 << func1
I don't know of a built-in composition operator that works like you want, but if this pattern is something you use frequently in your code and having such an operator would simplify your code, I think it's reasonable to define your own. For example:
> let (<<!) func2 func1 arg = func1 arg; func2 arg;;
val ( <<! ) : func2:('a -> 'b) -> func1:('a -> unit) -> arg:'a -> 'b
Or, if you know both functions are going to return unit, you can write it like this to constrain the output type to be unit:
> let (<<!) func2 func1 arg = func1 arg; func2 arg; ();;
val ( <<! ) : func2:('a -> unit) -> func1:('a -> unit) -> arg:'a -> unit
For composing of any number of functions of type f:'a->unit in any desired order you may simply fold their list:
("whatever",[ printfn "funX: %A"; printfn "funY: %A"; printfn "funZ: %A" ])
||> List.fold (fun arg f -> f arg; arg )
|> ignore
getting in FSI
funX: "whatever"
funY: "whatever"
funZ: "whatever"
val it : unit = ()

Tupled function composition

I'm curious why this
let f = (fun a b -> a, b) >> obj.Equals
gives the error
No accessible member or object constructor named 'Equals' takes 1 arguments
but this works
let f = (fun a -> a, a) >> obj.Equals
Without defining a new combinator operator:
let f = (fun a b -> a, b) >> (<<) obj.Equals
>> (<<) is a nice trick, and can also be extended for more arguments:
let compose3 f g = f >> (<<) ((<<) g)
val compose3 : ('a -> 'b -> 'c -> 'd) -> ('d -> 'e) -> ('a -> 'b -> 'c -> 'e)
Consider the types. (>>) has type ('a -> 'b) ->('b -> 'c) -> ('a -> 'c), but you're trying to call it with arguments of type 'a -> ('b -> 'a*'b) and obj * obj -> bool, which can't be made to fit together like that.
You could of course define a new combinator for composing binary and unary functions:
let ( >>* ) f g a b = f a b |> g
in which case you can use it in your example instead of (>>).

How to read F# type signatures?

I'm struggling with the F# type signature notation. For example let's say you have a Fold function:
let rec Fold combine acc l =
...
that may have this type signature:
('a -> 'b -> 'a) -> 'a -> list<'b> -> 'a
which I would read as
a function that has three arguments:
a function that takes an 'a, a 'b and returns an a'
an 'a
a list of 'b
and returns an 'a.
But then it would make more sense for my cavemen brain to express it as
('a, 'b -> 'a), 'a, list<'b> -> 'a
I'm sure there is a semantic reason why parameters are separated with an arrow exactly the same way as the function return type, but somehow I'm missing it and didn't found a clear explanation in books/articles so far. Every time I see a type signature I have to stop quite a bit of time to understand it. I feel like I'm just missing that little piece of the puzzle that makes the "decryption" obvious.
Can someone please enlighten me?
I'm sure there is a semantic reason
why parameters are separated with an
arrow exactly the same way as the
function return type, but somehow I'm
missing it and didn't found a clear
explanation in books/articles so far.
You're reading of the first function is correct. For instant deciphering, type signatures are expressed like this:
val functionName = inputType1 -> inputType2 -> ... -> inputTypeN -> returnType
Generally, arrow notation indicates a function is curry-able.
// val add4 : int -> int -> int -> int -> int
let add4 a b c d = a + b + c + d;;
// val f : (int -> int)
let f = add4 1 2 3 // returns (int -> int) waiting for last argument
Because the function is curried, you can technically write it like this:
// val add4 : int -> int -> int -> int -> int
let add4 = (fun a -> (fun b -> (fun c -> (fun d -> a + b + c + d))));;
// val f : (int -> int)
let f = fun x -> add4 1 2 3 x
If you think about it, the add4 signature is equivalent to this:
val add4 : int -> (int -> (int -> (int -> int) ) )
I believe we use arrow notation because it resembles the structure of the function when we explicitly curry arguments as shown above.
The signatures are written in that way because of what is called Currying. A slightly more accurate way of describing your function is that it takes a (function that takes a 'a and returns a function from a 'b to a 'a) and returns a function that takes a 'a and returns a function from a list<'b> to a 'a. Because of this the type signature can be rewritten as
('a -> 'b -> 'a) -> ('a -> (list<'b> -> 'a))
You could write a similar function in F# which has a type like you're proposing (but in F# it would be written as ('a * 'b -> 'a) * 'a * list<'b> -> 'a. However, the advantage of the existing function is that it's easy to partially apply it by only supplying a prefix of the arguments. For instance:
let sum = List.fold (+) 0
Using your definition, you'd have to write
let sum l = List.fold((fun (x,y) -> x + y), 0, l)
The reason for that is in Functional programming every function actually has only one parameter.
So lets say you have a function called Sum as :
int -> int -> int
It takes 2 int and return one int. Now if you call this function by just passing one int you won't get any compiler error, rather the return value will be of type int -> int. So you see this arrow notation fits with this behavior. This behavior is known as Currying.
Check out : http://en.wikipedia.org/wiki/Currying

Resources