How to read F# type signatures? - f#

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

Related

How to constrain the return type of a function with an arbitrary amount of arguments?

I would like to create a record type with a type annotation, with the constraint that the annotation must be a function that returns a certain type. Consider this example below:
type Foo<'Function> = {
Function: 'Function
}
I would 'Function to be able to be any function, as long as it returns for example int, so that
{Function = (fun a b c d e f g -> 2)}
{Function = (fun a -> 2)}
work, but
{Function = (fun a -> "")}
would be invalid.
As far as i understand F# functions, they are a nested structure of tuples, where the most inner second tuple field is the return type of the function, which is the reason why neither of these:
type Foo<('Input -> int)> = {
Function: ('Input -> int)
}
type ReturnsInt = FSharpFunc<'Input,int>
will work for any function with more than one argument, because the result type is encapsulated in the second annotation in either the signature or FSharpFunc<_,_>. Is there a way to realize this as a type annotation?
Edit
As Fyodor suggested in the comments below, this can be overcome by using only functions that have tupled arguments, leading to the function annotation being
FSharpFunc<argumentTuples,ReturnType>, e.g.:
type Foo<'ArgumentTuples> = {
Function: 'ArgumentTuples -> int
}
{Function = (fun (a,b,c,d,e,f,g) -> 2)} // works
{Function = (fun a -> 2)} // works
{Function = (fun a -> "")} // wont work
While this approach has its own problems and is not the specific answer to the original question, this workaround/workflow adaptation might be enough for me. I'll leave this question up (can't mark the comment as answer anyways)
Perhaps I'm missing something here, but why not simply define your type as:
type Foo<'InputType> = {
Function: ('InputType -> int)
}
Or more generic:
type Foo<'InputType, 'OutputType> = {
Function: ('InputType -> 'OutputType)
}
Edit: Ok, I see the problem.
So to use Fyodors solution, do something like this:
type Foo<'InputType> = {
Function: ('InputType -> int)
}
let add a b = a + b
let myFunction = {
Function = (fun (a,b) -> add a b)
}
Something along these lines might work for you, although you should be careful about not loosing the general picture. The branching may explode if there is a lot of complexity in your data model.
module FunctionTests
//define function types templates
type F1<'a> = 'a -> int
type F2<'a, 'b> = 'a -> 'b -> int
type F3<'a, 'b, 'c> = 'a -> 'b -> 'c -> int
type F4<'a, 'b, 'c, 'd> = 'a -> 'b -> 'c -> 'd -> int
//define actual functions
let f1 : F1<string> = fun x ->
printf "calling f1: %s\n" x
1
let f2 : F2<string, string> = fun x y ->
printf "calling f2: %s; %s\n" x y
2
let f3 : F3<string, string, int> = fun x y z ->
printf "calling f2: %s; %s; %d\n" x y z
3
let f4 : F4<string, string, int, int> = fun x y z v ->
printf "calling f2: %s; %s; %d; %d\n" x y z v
4
//define DU limiting to a subset of functions
type FunctionChooser =
| FF1 of F1<string>
| FF2 of F2<string, string>
| FF3 of F3<string, string, int>
| FF4 of F4<string, string, int, int>
//define a record with the DU
type FunctionRec = {Function : FunctionChooser}
//testing harness
let callFunction (functiondefs : FunctionRec) data otherdata intparam1 intparam2 =
match functiondefs.Function with
| FF1 fn -> fn data
| FF2 fn -> fn data otherdata
| FF3 fn -> fn data otherdata intparam1
| FF4 fn -> fn data otherdata intparam1 intparam2
//tests
let res1 = callFunction {Function=FF1 f1} "somedata" "otherdata" 13 14
let res2 = callFunction {Function=FF2 f2} "somedata" "otherdata" 13 14
let res3 = callFunction {Function=FF3 f3} "somedata" "otherdata" 13 14
let res4 = callFunction {Function=FF4 f4} "somedata" "otherdata" 13 14

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.

F# Create Factorial function without recursion, library functions or loops

In this video about functional programming at 35:14 Jim Weirich writes a function to compute factorial without using recursion, library functions or loops:
see image of Ruby code here
The code in Ruby
fx = ->(improver) {
improver.(improver)
}.(
->(improver) {
->(n) { n.zero ? 1 : n * improver.(improver).(n-1) }
}
)
I'm trying to express this approach F#
let fx =
(fun improver -> improver(improver))(
fun improver ->
fun n ->
if n = 0 then 1
else n * improver(improver(n - 1)))
I'm currently stuck at
Type mismatch. Expecting a 'a but given a 'a -> 'b
The resulting type would be infinite when unifying ''a' and ''a -> 'b'
I can't seem find the right type annotation or other way of expressing the function
Edit:
*without the rec keyword
Languages with ML-style type inference won't be able to infer a type for the term fun improver -> improver improver; they start by assuming the type 'a -> 'b for a lambda-definition (for some undetermined types 'a and 'b), so as the argument improver has type 'a, but then it's applied to itself to give the result (of type 'b), so improver must simultaneously have type 'a -> 'b. But in the F# type system there's no way to unify these types (and in the simply-typed lambda calculus there's no way to give this term a type at all). My answer to the question that you linked to in your comment covers some workarounds. #desco has given one of those already. Another is:
let fx = (fun (improver:obj->_) -> improver improver)
(fun improver n ->
if n = 0 then 1
else n * (improver :?> _) improver (n-1))
This is cheating, but you can use types
type Self<'T> = delegate of Self<'T> -> 'T
let fx1 = (fun (x: Self<_>) -> x.Invoke(x))(Self(fun x -> fun n -> if n = 0 then 1 else x.Invoke(x)(n - 1) * n))
type Rec<'T> = Rec of (Rec<'T> -> 'T)
let fx2 = (fun (Rec(f ) as r) -> f r)(Rec(fun ((Rec f) as r) -> fun n -> if n = 0 then 1 else f(r)(n - 1) * n))

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

Resources