F# Simple Signature - f#

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 ;)

Related

Defining overloaded operators on function

I want to define "relations", but defined as functions to Identity<'a>, seq<'a> and Option<'a>.
I have never defined overloaded operators in F#.
It would be sort of nice to use "+" !
open FSharpPlus.Data
type Relation =
// ('a -> Identity<'b>) -> ('b -> 'c) -> ('a -> 'c)
static member (+) (f,g) =
fun a -> g ((f a) |> Identity.run)
// ('a -> #seq<'b>) -> ('b -> #seq<'c>) -> ('a -> seq<'c>)
static member (+) (f , g ) =
fun a -> seq {
for b in f a do
yield! g b
}
// ('a -> seq<'b>) -> ('b -> Identity<'c>) -> ('a -> seq<'c>)
static member (+) (f,g) =
fun a -> seq {
for b in f a do
yield Identity.run (g b)
}
this compiles...
then I try to use it and;
member x.foo () =
let f1 : int -> Identity<int> = fun x -> Identity x
let f2 : int -> seq<int> = fun x -> Seq.singleton x
let x = f2 + f1
()
I get:
FS0043 Expecting a type supporting the operator '+' but given a function type. You may be missing an argument to a function.
am I doing something silly? (yes!)

Do function type parameter labels matter

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.

Pattern match on a list of tuples

If I want to add all the elements of a list of tuples, I get an error with the following
let rec addTupLst (xs: 'a * 'a list) =
match xs with
| (a, b) :: rst -> a + b + (addTupLst rst)
| _ -> 0
addTupLst [(1, 2)]
I get the warning
error FS0001: This expression was expected to have type
'a * 'a list
but here has type
'b list
Is it not possible to pattern match on a list of tuples this way, or is there another error?
You just forgot a pair of parens
let rec addTupLst (xs: ('a * 'a) list) =
match xs with
| (a, b) :: rst -> a + b + (addTupLst rst)
| _ -> 0
addTupLst [(1, 2)]
The problem is that you declare the function as taking a 'a * 'a list, but what you actually want to write is ('a * 'a) list.
This is one of the reasons why I don't really like the common but (IMO) inconsistent style of using prefix notation for type parameters for some built-in types and postfix notation for the rest. I prefer to write the type as list<'a * 'a>.

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)

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 (>>).

Resources