SKI combinator calculus or starship operator in F# - f#

Assuming we have two functions:
one that has a single parameter, like a partially applied addition:
let plus1 = (+) 1
// the same as let plus1 x = 1 + x
another that expects two parameters, like a multiplication:
let mult = (*)
we can now create a
let addOneAndMultiply x = mult x (plus1 x)
f x (g x) is usually called a SKI combinator calculus
in haskell, functions like that can be shortened with a starship <*> operator:
//haskell
mult <*> plus1
Is there any way to do the same SKI trick in F# ?

It's quite simple to do this in F#:
let (<*>) f g x = f x (g x)
To demonstrate that this works:
let plus1 = (+) 1
let mult = (*)
let addOneAndMultiply = mult <*> plus1
addOneAndMultiply 2 // Result: 6
addOneAndMultiply 3 // Result: 12
addOneAndMultiply 4 // Result: 20
P.S. If you want to make it a function instead of an operator, you just have to replace the (<*>) with the name of the function you want to define:
let starling f g x = f x (g x)

Related

Is there a modulo equivalent for (<) in functions?

For example; the following line
|> Seq.filter(fun i -> i < 123)
is the same thing as
|> Seq.filter((<) 123)
Is there such a thing for the modulo operator? I'm not sure what the 2nd variant is, and can't find it referenced in the documentation either, so it makes searching somewhat difficult. So for bonus points, please tell me what this operator is called! :)
Currently using:
|> Seq.filter (fun i -> i % 2 = 0)
Looking for something like:
|> Seq.filter ((%) 2 = 0)
Your first example is incorrect in saying that fun i -> i < 123 is equal to ((<) 123). That is actually equivalent to fun i -> 123 < i. Let me explain, every operator is just a function but infix rather than prefix. As an example
let (+) x y = x + y
let add x y = x + y
let (-) a b = a - b // notice that the first argument (a) is on the left side of the operator
let subs a b = a - b
knowing this, we can then reason about % and < the same way
let (%) x y = x % y
let (<) x y = x < y
// therefore
fun i -> i < 123
// is equivalent to
fun i -> (<) i 123
// and mathematically equiv to
((>=) 123)
// same with %
fun i -> i % 2
// is equiv to
fun i -> (%) i 2
// thus cant be reduced to eliminate the lambda
Another alternative, if you're dead-set on not writing out the lambda, is to lift it into a function:
let inline isEven x = x % 2 = 0
...
|> Seq.filter isEven
Alas, you are out of luck, because for partial application to be suitable, you need to swap both arguments of the mod operator. The lambda function is way more concise when taking into account that you are applying two operators, which requires function composition.
let flip f a b = f b a
{0..9}
|> Seq.filter ((flip (%) 2) >> ((=) 0))
|> (Seq.map string >> String.concat ", ")
// val it : string = "0, 2, 4, 6, 8"

Get even numbers with composition

I can obtain the even numbers in a list using the lambda syntax:
[1..10] |> List.filter (fun x -> x % 2 = 0)
But I want get it with composition, like this:
[1..10] |> List.filter ((% 2) >> (= 0))
Error: stdin(7,37): error FS0010: Unexpected integer literal in expression. Expected ')' or other token.
F# does not support operator sections. You can partially apply an operator by enclosing it in parentheses, like so:
let five = (+) 2 3
let add2 = (+) 2
let alsoFive = add2 3
However, this will not allow you to partially apply the right argument of the operator. In other words, F# does not offer anything equivalent to Haskell expression (/ 2). This can be worked around for commutative operators, such as addition or multiplication, because (+ 2) === (2 +), which in F# can be expressed as ((+) 2), but not for non-commutative ones.
The best you can do is declare the section as a separate function, like this:
let mod2 x = x % 2
[1..10] |> List.filter (mod2 >> ((=) 0))
If you absolutely insist on not declaring any more functions, you could try to do with a flip:
[1..10] |> List.filter ((flip (%) 2) >> ((=) 0))
But sadly, F# standard library does not provide a flip function either, so you'd have to declare it yourself anyway:
let inline flip f a b = f b a
Personally, I would rather go for increased readability and declare an isEven function:
let isEven x = (x % 2) = 0
[1..10] |> List.filter isEven

Desugared form of "let in"

What do the let (x = 0) in x * x translate to? A function (fun x -> x * x) 0) ? - This would make sense, as let bindings are expressions - and expressions must return values (just like functions).
Example:
let result1 =
(fun n1 -> (fun n2 ->
(fun n3 -> n1 + n2 + n3 ) 3) 2) 1
let result2 =
let n1 = 1 in
let n2 = 2 in
let n3 = 3 in
n1 + n2 + n3
let result3 =
let n1 = 1
let n2 = 2
let n3 = 3
n1 + n2 + n3
Am I right to assume that result3 is a sugared form of result2, and result2 a sugared form of result1?
Short: Do let in bindings translate to functions?
You can almost see let x = e1 in e2 as a syntactic sugar for (fun x -> e2) e1.
At the basic level, the two expressions mean the same thing - the compiler will probably compile them differently (depending on optimization levels and how it inlines things), but you could often use the second notation instead of the first one.
The one case where they differ is that ML-languages (including F#) only generalize function types written explicitly using the let keyword. This means that if you use fun, the language won't treat it as a generic function. If you want a generic function, you have to use let (and this is not just a compiler artifact, this is actually part of the language).
For example, the following uses let and it works:
let id = (fun x -> x) in ignore(id 1); ignore(id "A")
But the following does not work, because id is not a generic function:
(fun id -> ignore(id 1); ignore(id "A")) (fun x -> x)
The plain old let is just the lightweight syntax form of the verbose let … in.
From MSDN: Verbose Syntax (F#):
nested let bindings:
Lightweight syntax:
let f x =
let a = 1
let b = 2
x + a + b
Verbose syntax:
let f x =
let a = 1 in
let b = 2 in
x + a + b
The let bindings within these function don't translate to functions themselves, however. Both of these translate to identical CIL code:
f:
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.1
IL_0003: add
IL_0004: ldc.i4.2
IL_0005: add
IL_0006: ret
Note that the only function here is the outer function f. The variables a and b are evaluated as constants within the scope of f.
let x = <val> in <expr> is functionally equivalent to (fun x -> <expr>) <val>.
<expr> is an expression
<val> is a value
The in keyword is optional.

How does F# pipeline operator work

have a code:
//e = 1/2*Sum((yi -di)^2)
let error y d =
let map =
Array.map2 (fun y d -> (y - d) ** 2.0) y d
let sum =
Array.sum map
(sum / 2.0)
let error2 y d =
Array.map2 (fun y d -> (y - d) ** 2.0) y d
|> Array.sum
|> (/) 2.0
as i understood those functions should produce the same results, but there are a big difference in the results. Can anyone explain this?
p.s. Simplified example:
let test = [|1..10|]
let res = test
|> Array.sum
|> (/) 5
i expect test = 11 (sum(1..10) = 55 and then 55 / 5) but after Array.sum pipeline is not working as i want(as result test = 0).
another alternative is to use the reverse pipe operator (<|) so that partial application of (/) is done with arguments in correct order:
let error2 y d =
Array.map2 (fun y d -> (y - d) ** 2.0) y d
|> Array.sum
|> (/) <| 2.0
Edit: see if this helps clarify
x/y = (/) x y = y |> (/) x = x |> (/) <| y
All those are equivalent. The pipe operators are defined as:
(|>) x f = f x
(<|) f x = f x
where f is a function and x is some value. The reverse pipe doesn't look like it does much but it can help clean up some code in certain situations.
You seem to misunderstand order of arguments in infix functions.
You can expand the point-free form as follows:
x |> (/) 5
<=> (/) 5 x
<=> 5 / x
So it's is the reverse of what you expect. It only works fine for commutative functions like (+), (*), etc. If you're keen on point-free style, the flip function is helpful to be used with |>:
let inline flip f x y = f y x
let error2 y d =
Array.map2 (fun y d -> (y - d) ** 2.0) y d
|> Array.sum
|> flip (/) 2.0
The / operator does not work the way you have assumed. You just need to be a bit more explicit and change the last line in error2 to
fun t -> t/2.0
and then it should all work.
The answers being out by a factor of 4 was the giveaway here.
EDIT: To understand what happens with / here consider what happens when you expand out |>
The following are all equivalent
a |> (/) b
((/) b) a //by removing |>
a / b //what happens when / is reinterpreted as a function

Partial function application for a non-symmetric operator using point-free style in F#?

How can I create a partial function application for a non-symmetric operator such as the modulus operator with regards to the first argument without any argument names in F#? My first attempt was
let mod10 = (%) 10 which of course translates to
mod10(x) = 10 mod x instead of the desired
mod10(x) = x mod 10.
Certainly I could write
let mod10 x = (%)x 10 but I'd like to not have to name the argument so is there some placeholder that can be used, something like
let mod10 = (%)_ 10?
Here's solution based on functional composition.
let mod10 = (%) >> (|>) 10
UPD Here was a wordy explanation, but programmers speak the code, so I guess the following will describe it much better, in a manner of mathematical proof.
The following expressions are equal:
let m1 x = x % 10
let m2 x = (%) x 10 // x (op) y = (op) x y
let m3 x = ((%) x) 10 // f x y = (f x) y
let m4 x = 10 |> ((%) x) // f x = x |> f
let m5 x = ((|>) 10) ((%) x) // x |> f = (|>) x f
let m6 x = ((%) x) |> ((|>) 10) // f x = x |> f
let m7 x = (x |> (%)) |> ((|>) 10) // (op) x = x |> (op)
let m8 x = x |> ((%) >> ((|>) 10)) // f(x) |> g = x |> (f >> g)
let m9 = (%) >> ((|>) 10) // remove formal argument
let m10 = (%) >> (|>) 10 // remove unnecessary parenthesis
Alternative syntax:
let mod10_2 = (|>) 10 << (%)
You can define flip function which is common in point-free style:
let inline flip f x y = f y x
and use it like this:
let (%-) = flip (%)
let mod10 = (%-) 10
or directly like this:
let mod10 = flip (%) 10
Point-free style is not always readable (as in this example) and not popular in F# programming.

Resources