OCaml, F# successive, cascading let bindings - f#

It is typical in OCaml or F# to have successive let bindings in the form:
let a1 = ...
let a2 = ...
let a3 = ...
let f1 = ...
let f2 = ...
let f3 = ...
f3 a1 a2 a3
In many cases some of these let bindings (e.g. f1 and f2 in the example above) are only used as building blocks of the expression or function immediately following them and not referenced again afterwards. In other cases some values are indeed used at the end of the "chain" (e.g. a1, a2 and a3 in the example above). Is there any syntactic idiom to make these differences in scope explicit?

On can use this to make clear that temp is used only in the definition of a1:
let a1 =
let temp = 42 in
temp + 2 in
let a2 = ...
The scope of temp is indeed restricted to the definition of a1.
Another template is reusing the same name to hide its previous use, thus also making it clear that the previous use is temporary:
let result = input_string inchan in
let result = parse result in
let result = eval result in
result
Reusing the same name is debatable, though.
Of course one always has comments and empty lines:
let a1 = ...
let a2 = ...
let a3 = ...
(*We now define f3:*)
let f1 = ...
let f2 = ...
let f3 = ...
f3 a1 a2 a3
Edit: as pointed out by fmr, I'm also fond of the pipe operator. It's not defined by default in OCaml, use
let (|>) x f = f x;;
Then you can write something like
input_string inchan |> parse |> eval |> print

In addition to jrouquie's answer, you can avoid giving names to intermediate values by judicious use of function composition and other combinators. I especially like the following three provided by Batteries:
# let ( |> ) x f = f x;;
val ( |> ) : 'a -> ('a -> 'b) -> 'b = <fun>
# let ( |- ) f g x = g (f x);;
val ( |- ) : ('a -> 'b) -> ('b -> 'c) -> 'a -> 'c = <fun>
# let flip f x y = f y x;;
val flip : ('a -> 'b -> 'c) -> 'b -> 'a -> 'c = <fun>
A small example using |> is
# [1;2;3]
|> List.map string_of_int
|> String.concat "; "
|> Printf.sprintf "[%s]";;
- : string = "[1; 2; 3]"
You'll end up needing |- and flip in more realistic examples. This is known as point-free or tacit programming.

Related

F# Option chaining

The F# Option type is a good way to return 'result or failure' from a function.
Sometimes you need to chain such functions, along the lines of:
Call the first function
If it returns Some whatever, pass the whatever to the second function and return the result
Otherwise, just immediately return None
Of course this can be done with pattern matching; an actual code fragment from a function that is itself implementing pattern matching in this way:
match mtch env a0 a1 with
|Some env->
mtch env b0 b1
|None->
None
But it feels like there should be a more compact way to express this common idiom, perhaps with a higher order function. Is there something like that?
There's an Option module in FSharp.Core, providing "basic operations on options." Specifically, the signature of Option.bind matches your use case:
binder:('T -> 'U option) -> option:'T option -> 'U option
It states in the VisualStudio pop-up hint that bind f inp evaluates to match inp with None -> None | Some x -> f x.
// The actual argument values are not important here
let env, a0, a1, b0, b1 = (), (), (), (), ()
let mtch env _ _ = Some env // or might be None
match mtch env a0 a1 with
|Some env -> mtch env b0 b1
|None -> None
mtch env a0 a1
|> Option.bind (fun env -> mtch env b0 b1)
You might even improve on that by defining custom operators for operations on options.
let (>>=) ma f = Option.bind f ma
let (>>.) ma f = Option.map f ma
mtch env a0 a1
>>= fun env -> mtch env b0 b1
>>= ...
You could use Computation Expressions. I'll use an example found on this page: https://fsharpforfunandprofit.com/posts/computation-expressions-intro/
Create the computation:
type MaybeBuilder() =
member _.Bind(x, f) =
match x with
| None -> None
| Some a -> f a
member _.Return(x) =
Some x
let maybe = new MaybeBuilder()
An example function that returns an Option:
let divideBy bottom top =
if bottom = 0
then None
else Some(top/bottom)
A workflow using the Computation and chaining divideBy:
let divideByWorkflow init x y z =
maybe{
let! a = init |> divideBy x
let! b = a |> divideBy y
let! c = b |> divideBy z
return c
}
Usage examples:
let good = divideByWorkflow 12 3 2 1 //Some 2
let bad = divideByWorkflow 12 3 0 1 //None

Church Numerals in F#

I have been trying to implement church numerals in F#. They were briefly introduced in a course at college and I may have gone down the rabbit hole a bit since then. I have working Predecessor, Successor, Add and Operations but I can't get subtract to work. I'm trying to implement subtract b applying predecessor multiple times. What I find peculiar is that the penultimate line in my code works but what I assume is equivalent, the last line, does not work. There is a type mismatch.
I'm very new to F# so any help would be appreciated. Thank you.
//Operations on tuples
let fst (a,b) = a
let snd (a,b) = b
let pair a b = (a,b)
//Some church numerals
let c0 (f:('a -> 'a)) = id
let c1 (f:('a -> 'a)) = f
let c2 f = f << f
let c3 f = f << f << f
let c4 f = f << f << f << f
// Successor and predecessor
let cSucc (b,(cn:('a->'a)->('a->'a))) = if b then (b, fun f -> f << (cn f)) else (true, fun f -> (cn f))
let cPred (cn:('a->'a)->('a->'a)) = fun f -> snd (cn cSucc (false, c0)) f
//let cSucc2 cn = fun f -> f << (cn f)
// Add, Multiply and Subtract church numerals
let cAdd cn cm = fun f -> cn f << cm f
let cMult cn cm = cn >> cm
let cSub cn cm = cm cPred cn
//Basic function for checking validity of numeral operations
let f = (fun x -> x + 1)
//This works
(cPred << cPred) c3 f 0
//This doesn't
c2 cPred c3 f 0
This is the type mismatch error given (Intellisense says this is an error with cPred on the last line of the code). I can see the output type is inferred wrong. Is there a way to fix it or is there something fundamentally wrong with how I have written this implementation?
'((bool * (('a -> 'a) -> 'a -> 'a) -> bool * (('a -> 'a) -> 'a -> 'a)) -> bool * (('a -> 'a) -> 'a -> 'a) -> bool * (('a -> 'a) -> 'a -> 'a)) -> (bool * (('a -> 'a) -> 'a -> 'a) -> bool * (('a -> 'a) -> 'a -> 'a)) -> bool * (('a -> 'a) -> 'a -> 'a) -> bool * (('a -> 'a) -> 'a -> 'a)'
but given a
'((bool * (('a -> 'a) -> 'a -> 'a) -> bool * (('a -> 'a) -> 'a -> 'a)) -> bool * (('a -> 'a) -> 'a -> 'a) -> bool * (('a -> 'a) -> 'a -> 'a)) -> ('a -> 'a) -> 'a -> 'a'
The types ''a' and 'bool * (('a -> 'a) -> 'a -> 'a)' cannot be unified.
In the below explanation I will assume a definition of type CN<'a> = ('a -> 'a) -> 'a -> 'a (where "CN" stands for "Church Numeral") in order to shorten the explanation and reduce clutter.
Your attempted application of c2 to cPred fails, because c2 expects an argument of type 'a -> 'a, but cPred is not such function.
You may expect cPred to match the expected type, because you have declared it as CN<'a> -> CN<'a>, but that is not the true type. Because you are applying argument cn to type bool*CN<'a> -> bool*CN<'a> (which is the type of cSucc), the compiler infers that cn must have type of CN<bool*CN<'a>>, and therefore cPred gets the type of CN<bool*CN<'a>> -> CN<'a>, which does not match what c2 expects.
All of this comes down to this fact: functions lose their genericity when you pass them around as values.
Consider a simpler example:
let f (g: 'a -> 'a list) = g 1, g "a"
Such definition will not compile, because 'a is a parameter of f, not a parameter of g. Therefore, for a given execution of f, a specific 'a must be chosen, and it cannot be both int and string at the same time, and therefore, g cannot be applied to both 1 and "a".
Similarly, cn in cPred gets fixed to type bool*CN<'a> -> bool*CN<'a>, thus making the type of cPred itself incompatible with CN<_>.
In simple cases, there is an obvious workaround: pass g twice.
let f g1 g2 = g1 1, g2 "a"
let g x = [x]
f g g
// > it : int list * string list = [1], ["a"]
This way, g will lose genericity both times, but it will be specialized to different types - the first instance to int -> int list, the second - to string -> string list.
However, this is only a half-measure, suitable for the simplest cases only. A general solution will require the compiler to understand that we want 'a to be a parameter of g, not a parameter of f (this is usually referred to as "higher-rank type"). In Haskell (more specifically, GHC), there is a straightforward way to do this, with the RankNTypes extension enabled:
f (g :: forall a. a -> [a]) = (g 1, g "a")
g x = [x]
f g
==> ([1], ["a"])
Here, I explicitly tell the compiler that the parameter g has its own generic parameter a by including forall a in its type declaration.
F# does not have such explicit support for this, but it does offer a different feature that can be used to accomplish the same result - interfaces. Interfaces may have generic methods, and these methods do not lose genericity when interface instances are passed around. So we can reformulate the above simple example like this:
type G =
abstract apply : 'a -> 'a list
let f (g: G) = g.apply 1, g.apply "a"
let g = { new G with override this.apply x = [x] }
f g
// it : int list * string list = ([1], ["a"])
Yes, the syntax for declaring such "higher-rank functions" is heavy, but that's all F# has to offer.
So, applying this to your original problem, we need to declare CN as an interface:
type CN =
abstract ap : ('a -> 'a) -> 'a -> 'a
Then we can construct some numbers:
let c0 = { new CN with override __.ap f x = x }
let c1 = { new CN with override __.ap f x = f x }
let c2 = { new CN with override __.ap f x = f (f x) }
let c3 = { new CN with override __.ap f x = f (f (f x)) }
let c4 = { new CN with override __.ap f x = f (f (f (f x))) }
Then cSucc and cPred:
let cSucc (b,(cn:CN)) =
if b
then (b, { new CN with override __.ap f x = f (cn.ap f x) })
else (true, cn)
let cPred (cn:CN) = snd (cn.ap cSucc (false, c0))
Note that cPred now has inferred type of CN -> CN, exactly what we need.
Arithmetic functions:
let cAdd (cn: CN) (cm: CN) = { new CN with override __.ap f x = cn.ap f (cm.ap f x) }
let cMult (cn: CN) (cm: CN) = { new CN with override __.ap f x = cn.ap cm.ap f x }
let cSub (cn: CN) (cm: CN) = cm.ap cPred cn
Note, all of them get the inferred type of CN -> CN -> CN, as expected.
And finally, your examples:
let f = (fun x -> x + 1)
//This works
((cPred << cPred) c3).ap f 0
//This also works now
(c2.ap cPred c3).ap f 0

Is there a way to make this continuation passing with codata example work in F#?

type Interpreter<'a> =
| RegularInterpreter of (int -> 'a)
| StringInterpreter of (string -> 'a)
let add<'a> (x: 'a) (y: 'a) (in_: Interpreter<'a>): 'a =
match in_ with
| RegularInterpreter r ->
x+y |> r
| StringInterpreter r ->
sprintf "(%s + %s)" x y |> r
The error message of it not being able to resolve 'a at compile time is pretty clear to me. I am guessing that the answer to the question of whether it is possible to make the above work is no, short of adding functions directly into the datatype. But then I might as well use an interface, or get rid of generic parameters entirely.
Edit: Mark's reply does in fact do what I asked, but let me extend the question as I did not explain it adequately. What I am trying to do is do with the technique above is imitate what what was done in this post. The motivation for this is to avoid inlined functions as they have poor composability - they can't be passed as lambdas without having their generic arguments specialized.
I was hoping that I might be able to work around it by passing an union type with a generic argument into a closure, but...
type Interpreter<'a> =
| RegularInterpreter of (int -> 'a)
| StringInterpreter of (string -> 'a)
let val_ x in_ =
match in_ with
| RegularInterpreter r -> r x
| StringInterpreter r -> r (string x)
let inline add x y in_ =
match in_ with
| RegularInterpreter r ->
x in_ + y in_ |> r
| StringInterpreter r ->
sprintf "(%A + %A)" (x in_) (y in_) |> r
let inline mult x y in_ =
match in_ with
| RegularInterpreter r ->
x in_ * y in_ |> r
| StringInterpreter r ->
sprintf "(%A * %A)" (x in_) (y in_) |> r
let inline r2 in_ = add (val_ 1) (val_ 3) in_
r2 (RegularInterpreter id)
r2 (StringInterpreter id) // Type error.
This last line gives a type error. Is there a way around this? Though I'd prefer the functions to not be inlined due to the limits they place on composability.
Remove the type annotations:
let inline add x y in_ =
match in_ with
| RegularInterpreter r ->
x + y |> r
| StringInterpreter r ->
sprintf "(%A + %A)" x y |> r
You'll also need to make a few other changes, which I've also incorporated above:
Change the format specifiers used with sprintf to something more generic. When you use %s, you're saying that the argument for that placeholder must be a string, so the compiler would infer x and y to be string values.
Add the inline keyword.
With these changes, the inferred type of add is now:
x: ^a -> y: ^b -> in_:Interpreter<'c> -> 'c
when ( ^a or ^b) : (static member ( + ) : ^a * ^b -> int)
You'll notice that it works for any type where + is defined as turning the input arguments into int. In practice, that's probably going to mean only int itself, unless you define a custom operator.
FSI smoke tests:
> add 3 2 (RegularInterpreter id);;
val it : int = 5
> add 2 3 (StringInterpreter (fun _ -> 42));;
val it : int = 42
The compiler ends up defaulting to int, and the kind of polymorphism you want is difficult to achieve in F#. This article articulates the point.
Perhaps, you could work the dark arts using FSharp.Interop.Dynamic but you lose compile time checking which sort of defeats the point.
I've come to the conclusion that what I am trying to is impossible. I had a hunch that it was already, but the proof is in the following:
let vale (x,_,_) = x
let adde (_,x,_) = x
let multe (_,_,x) = x
let val_ x d =
let f = vale d
f x
let add x y d =
let f = adde d
f (x d) (y d)
let mult x y d =
let f = multe d
f (x d) (y d)
let in_1 =
let val_ (x: int) = x
let add x y = x+y
let mult x y = x*y
val_,add,mult
let in_2 =
let val_ (x: int) = string x
let add x y = sprintf "(%s + %s)" x y
let mult x y = sprintf "(%s * %s)" x y
val_,add,mult
let r2 d = add (val_ 1) (val_ 3) d
//let test x = x in_1, x in_2 // Type error.
let a2 = r2 in_1 // Works
let b2 = r2 in_2 // Works
The reasoning goes that if it cannot be done with plain functions passed as arguments, then it definitely won't be possible with interfaces, records, discriminated unions or any other scheme. The standard functions are more generic than any of the above, and if they cannot do it then this is a fundamental limitation of the language.
It is not the lack of HKTs that make the code ungeneric, but something as simple as this. In fact, going by the Finally Tagless paper linked to in the Reddit post, Haskell has the same problem with needing to duplicate interpreters without the impredicative types extension - though I've looked around and it seem that impredicative types will be removed in the future as the extension is difficult to maintain.
Nevertheless, I do hope this is only a current limitation of F#. If the language was dynamic, the code segment above would in fact run correctly.
Unfortunately, it's not completely clear to me what you're trying to do. However, it seems likely that it's possible by creating an interface with a generic method. For example, here's how you could get the code from your answer to work:
type I = abstract Apply : ((int -> 'a) * ('a -> 'a -> 'a) * ('a -> 'a -> 'a)) -> 'a
//let test x = x in_1, x in_2 // Type error.
let test (i:I) = i.Apply in_1, i.Apply in_2
let r2' = { new I with member __.Apply d = add (val_ 1) (val_ 3) d }
test r2' // no problem
If you want to use a value (e.g. a function input) generically, then in most cases the cleanest way is to create an interface with a generic method whose signature expresses the required polymorphism.

Built in equality of lists using a custom comparison function?

Is there a built-in function which does the following?
let rec listsEqual xl yl f =
match xl, yl with
| [], [] -> true
| [], _ | _, [] -> false
| xh::xt, yh::yt -> if f xh yh then listsEqual xt yt f else false
Updated, further elaboration: and in general is there any way to tap in to structural comparison but using a custom comparison function?
List.forall2 : (('a -> 'b -> bool) -> 'a list -> 'b list -> bool)
But it takes f before the lists. You can create your function like this:
let listsEqual x y f =
if List.length x = List.length y then
List.forall2 f x y
else
false
Remember that List.forall2 assumes the lengths are the same.
Concerning Seq.compareWith, you wrote:
not quite, two problems 1) expects the
two sequences be of the same type, 2)
doesn't short circuit
2) is wrong, the function really does a court-circuit.
1) is true. Take Seq.compareWith from F# library, modify (or remove) the type annotation and it will work for sequences of different types.
[<CompiledName("CompareWith")>]
let compareWith (f:'T1 -> 'T2 -> int) (source1 : seq<'T1>) (source2: seq<'T2>) =
//checkNonNull "source1" source1
//checkNonNull "source2" source2
use e1 = source1.GetEnumerator()
use e2 = source2.GetEnumerator()
let rec go () =
let e1ok = e1.MoveNext()
let e2ok = e2.MoveNext()
let c = (if e1ok = e2ok then 0 else if e1ok then 1 else -1)
if c <> 0 then c else
if not e1ok || not e2ok then 0
else
let c = f e1.Current e2.Current
if c <> 0 then c else
go ()
go()
Now, you can send an email to fsbugs (# microsoft.com) and ask them to remove the type constraint in the next F# release.

How do you curry the 2nd (or 3rd, 4th, ...) parameter in F# or any functional language?

I'm just starting up with F# and see how you can use currying to pre-load the 1st parameter to a function. But how would one do it with the 2nd, 3rd, or whatever other parameter? Would named parameters to make this easier? Are there any other functional languages that have named parameters or some other way to make currying indifferent to parameter-order?
Typically you just use a lambda:
fun x y z -> f x y 42
is a function like 'f' but with the third parameter bound to 42.
You can also use combinators (like someone mentioned Haskell's "flip" in a comment), which reorder arguments, but I sometimes find that confusing.
Note that most curried functions are written so that the argument-most-likely-to-be-partially-applied comes first.
F# has named parameters for methods (not let-bound function values), but the names apply to 'tupled' parameters. Named curried parameters do not make much sense; if I have a two-argument curried function 'f', I would expect that given
let g = f
let h x y = f x y
then 'g' or 'h' would be substitutable for 'f', but 'named' parameters make this not necessarily true. That is to say, 'named parameters' can interact poorly with other aspects of the language design, and I personally don't know of a good design offhand for 'named parameters' that interacts well with 'first class curried function values'.
OCaml, the language that F# was based on, has labeled (and optional) arguments that can be specified in any order, and you can partially apply a function based on those arguments' names. I don't believe F# has this feature.
You might try creating something like Haskell's flip function. Creating variants that jump the argument further in the argument list shouldn't be too hard.
let flip f a b = f b a
let flip2 f a b c = f b c a
let flip3 f a b c d = f b c d a
Just for completeness - and since you asked about other functional languages - this is how you would do it in OCaml, arguably the "mother" of F#:
$ ocaml
# let foo ~x ~y = x - y ;;
val foo : x:int -> y:int -> int = <fun>
# foo 5 3;;
- : int = 2
# let bar = foo ~y:3;;
val bar : x:int -> int = <fun>
# bar 5;;
- : int = 2
So in OCaml you can hardcode any named parameter you want, just by using its name (y in the example above).
Microsoft chose not to implement this feature, as you found out... In my humble opinion, it's not about "poor interaction with other aspects of the language design"... it is more likely because of the additional effort this would require (in the language implementation) and the delay it would cause in bringing the language to the world - when in fact only few people would (a) be aware of the "stepdown" from OCaml, (b) use named function arguments anyway.
I am in the minority, and do use them - but it is indeed something easily emulated in F# with a local function binding:
let foo x y = x - y
let bar x = foo x 3
bar ...
It's possible to do this without declaring anything, but I agree with Brian that a lambda or a custom function is probably a better solution.
I find that I most frequently want this for partial application of division or subtraction.
> let halve = (/) >> (|>) 2.0;;
> let halfPi = halve System.Math.PI;;
val halve : (float -> float)
val halfPi : float = 1.570796327
To generalize, we can declare a function applySecond:
> let applySecond f arg2 = f >> (|>) arg2;;
val applySecond : f:('a -> 'b -> 'c) -> arg2:'b -> ('a -> 'c)
To follow the logic, it might help to define the function thus:
> let applySecond f arg2 =
- let ff = (|>) arg2
- f >> ff;;
val applySecond : f:('a -> 'b -> 'c) -> arg2:'b -> ('a -> 'c)
Now f is a function from 'a to 'b -> 'c. This is composed with ff, a function from 'b -> 'c to 'c that results from the partial application of arg2 to the forward pipeline operator. This function applies the specific 'b value passed for arg2 to its argument. So when we compose f with ff, we get a function from 'a to 'c that uses the given value for the 'b argument, which is just what we wanted.
Compare the first example above to the following:
> let halve f = f / 2.0;;
> let halfPi = halve System.Math.PI;;
val halve : f:float -> float
val halfPi : float = 1.570796327
Also compare these:
let filterTwoDigitInts = List.filter >> (|>) [10 .. 99]
let oddTwoDigitInts = filterTwoDigitInts ((&&&) 1 >> (=) 1)
let evenTwoDigitInts = filterTwoDigitInts ((&&&) 1 >> (=) 0)
let filterTwoDigitInts f = List.filter f [10 .. 99]
let oddTwoDigitInts = filterTwoDigitInts (fun i -> i &&& 1 = 1)
let evenTwoDigitInts = filterTwoDigitInts (fun i -> i &&& 1 = 0)
Alternatively, compare:
let someFloats = [0.0 .. 10.0]
let theFloatsDividedByFour1 = someFloats |> List.map ((/) >> (|>) 4.0)
let theFloatsDividedByFour2 = someFloats |> List.map (fun f -> f / 4.0)
The lambda versions seem to be easier to read.
In Python, you can use functools.partial, or a lambda. Python has named arguments.
functools.partial can be used to specify the first positional arguments as well as any named argument.
from functools import partial
def foo(a, b, bar=None):
...
f = partial(foo, bar='wzzz') # f(1, 2) ~ foo(1, 2, bar='wzzz')
f2 = partial(foo, 3) # f2(5) ~ foo(3, 5)
f3 = lambda a: foo(a, 7) # f3(9) ~ foo(9, 7)

Resources