It's not a practically important issue, but I'd like to see an example of tacit programming in F# where my point-free functions can have multiple arguments (not in form of a list or tuple).
And secondly, how such functions can manipulate a complex data structure. I'm trying it out in F# Interactive, but have no success yet.
I tried, for instance:
> (fun _ -> (fun _ -> (+))) 333 222 111 555
Is that right way?
And:
> (fun _ -> (fun _ -> (+))) "a" "b" "c" "d";;
val it : string = "cd"
F# doesn't contain some of the basic functions that are available in Haskell (mainly because F# programmers usually prefer the explicit style of programming and use pointfree style only in the most obvious cases, where it doesn't hurt readability).
However you can define a few basic combinators like this:
// turns curried function into non-curried function and back
let curry f (a, b) = f a b
let uncurry f a b = f (a, b)
// applies the function to the first/second element of a tuple
let first f (a, b) = (f a, b)
let second f (a, b) = (a, f b)
Now you can implement the function to add lengths of two strings using combinators as follows:
let addLengths =
uncurry (( (first String.length) >> (second String.length) ) >> (curry (+)))
This constructs two functions that apply String.length to first/second element of a tuple, then composes them and then adds the elements of the tuple using +. The whole thing is wrapped in uncurry, so you get a function of type string -> string -> int.
In F#, the arity of functions is fixed, so you're not going to be able to write both
(op) 1 2
and
(op) 1 2 3 4
for any given operator op. You will need to use a list or other data structure if that's what you want. If you're just trying to avoid named variables, you can always do "1 + 2 + 3 + 4". The most idiomatic way to add a list of numbers in F# is List.sum [1;2;3;4], which also avoids variables.
Related
Can the function createTuple below be expressed pointfree?
let createTuple = fun v -> (v, v*2)
createTuple 2 |> printfn "%A" // (2,4)
The F# library does not provide many functions for writing code in point-free style (mainly because it is not particularly idiomatic way of writing F#), so you cannot write your createTuple function using just what is available in the core library.
If you really wanted to do this, you could define a couple of helper combinators for working with tuples:
/// Duplicates any given value & returns a tuple with two copies of it
let dup a = a, a
/// Transforms the first element using given function
let mapFst f (a, b) = (f a, b)
/// Transforms the second element (not needed here, but adding for symmetry)
let mapSnd f (a, b) = (a, f b)
With these, you could implement your function in a point-free way:
let createTuple = dup >> mapSnd ((*) 2)
This does the same thing as your function. I think it is significantly harder to decipher what is going on here and I would never actually write that code, but that's another issue :-).
let mapTuple f (a,b) = (f a, f b)
I'm trying to create a function that applies a function f to both items in a tuple and returns the result as a tuple. F# type inference says that mapTuple returns a 'b*'b tuple. It also assumes that a and b are of the same type.
I want to be able to pass two different types as parameters. You would think that wouldn't work because they both have to be passed as parameters to f. So I thought if they inherited from the same base class, it might work.
Here is a less generic function for what I am trying to accomplish.
let mapTuple (f:Map<_,_> -> Map<'a,'b>) (a:Map<int,double>,b:Map<double, int>) = (f a, f b)
However, it gives a type mismatch error.
How do I do it? Is what I am trying to accomplish even possible in F#?
Gustavo is mostly right; what you're asking for requires higher-rank types. However,
.NET (and by extension F#) does support (an encoding of) higher-rank types.
Even in Haskell, which supports a "nice" way of expressing such types (once you've enabled the right extension), they wouldn't be inferred for your example.
Digging into point 2 may be valuable: given map f a b = (f a, f b), why doesn't Haskell infer a more general type than map :: (t1 -> t) -> t1 -> t1 -> (t, t)? The reason is that once you include higher-rank types, it's not typically possible to infer a single "most general" type for a given expression. Indeed, there are many possible higher-rank signatures for map given its simple definition above:
map :: (forall t. t -> t) -> x -> y -> (x, y)
map :: (forall t. t -> z) -> x -> y -> (z, z)
map :: (forall t. t -> [t]) -> x -> y -> ([x], [y])
(plus infinitely many more). But note that these are all incompatible with each other (none is more general than another). Given the first one you can call map id 1 'c', given the second one you can call map (\_ -> 1) 1 'c', and given the third one you can call map (\x -> [x]) 1 'c', but those arguments are only valid with each of those types, not with the other ones.
So even in Haskell you need to specify the particular polymorphic signature you want to use - this may be a bit of a surprise if you're coming from a more dynamic language. In Haskell, this is relatively clean (the syntax is what I've used above). However, in F# you'll have to jump through an additional hoop: there's no clean syntax for a "forall" type, so you'll have to create an additional nominal type instead. For example, to encode the first type above in F# I'd write something like this:
type Mapping = abstract Apply : 'a -> 'a
let map (m:Mapping) (a, b) = m.Apply a, m.Apply b
let x, y = map { new Mapping with member this.Apply x = x } (1, "test")
Note that in contrast to Gustavo's suggestion, you can define the first argument to map as an expression (rather than forcing it to be a member of some separate type). On the other hand, there's clearly a lot more boilerplate than would be ideal...
This problem has to do with rank-n types which are supported in Haskell (through extensions) but not in .NET type system.
One way I found to workaround this limitation is to pass a type with a single method instead of a function and then define an inline map function with static constraints, for example let's suppose I have some generic functions: toString and toOption and I want to be able to map them to a tuple of different types:
type ToString = ToString with static member inline ($) (ToString, x) = string x
type ToOption = ToOption with static member ($) (ToOption, x) = Some x
let inline mapTuple f (x, y) = (f $ x, f $ y)
let tuple1 = mapTuple ToString (true, 42)
let tuple2 = mapTuple ToOption (true, 42)
// val tuple1 : string * string = ("True", "42")
// val tuple2 : bool option * int option = (Some true, Some 42)
ToString will return the same type but operating with arbitrary types. ToOption will return two Generics of different types.
By using a binary operator type inference creates the static constraints for you and I use $ because in Haskell it means apply so a nice detail is that for haskellers f $ x reads already apply x to f.
At the risk of stating the obvious, a good enough solution might be to have a mapTuple that takes two functions instead of one:
let mapTuple fa fb (a, b) = (fa a, fb b)
If your original f is generic, passing it as fa and fb will give you two concrete instantiations of the function with the types you're looking for. At worst, you just need to pass the same function twice when a and b are of the same type.
Is there some form of built-in / term I don't know that kinda-but-its-different 'composes' two 'a -> unit functions to yield a single one; e.g.:
let project event =
event |> logDirections
event |> stashDirections
let dispatch (batch:EncodedEventBatch) =
batch.chooseOfUnion () |> Seq.iter project
might become:
let project = logDirections FOLLOWEDBY stashDirections
let dispatch (batch:EncodedEventBatch) =
batch.chooseOfUnion () |> Seq.iter project
and then:
let dispatch (batch:EncodedEventBatch) =
batch.chooseOfUnion () |> Seq.iter (logDirections FOLLOWEDBY stashDirections)
I guess one might compare it to tee (as alluded to in FSFFAP's Railway Oriented Programming series).
(it needs to pass the same arg to both and I'm seeking to run them sequentially without any exception handling trickery concerns etc.)
(I know I can do let project fs arg = fs |> Seq.iter (fun f -> f arg) but am wondering if there is something built-in and/or some form of composition lib I'm not aware of)
The apply function from Klark is the most straightforward way to solve the problem.
If you want to dig deeper and understand the concept more generally, then you can say that you are lifting the sequential composition operation from working on values to work on functions.
First of all, the ; construct in F# can be viewed as sequential composition operator. Sadly, you cannot quite use it as one, e.g. (;) (because it is special and lazy in the second argument) but we can define our own operator instead to explore the idea:
let ($) a b = a; b
So, printfn "hi" $ 1 is now a sequential composition of a side-effecting operation and some expression that evaluates to 1 and it does the same thing as printfn "hi"; 1.
The next step is to define a lifting operation that turns a binary operator working on values to a binary operator working on functions:
let lift op g h = (fun a -> op (g a) (h a))
Rather than writing e.g. fun x -> foo x + bar x, you can now write lift (+) foo bar. So you have a point-free way of writing the same thing - just using operation that works on functions.
Now you can achieve what you want using the lift function and the sequential composition operator:
let seq2 a b = lift ($) a b
let seq3 a b c = lift ($) (lift ($) a b) c
let seqN l = Seq.reduce (lift ($)) l
The seq2 and seq3 functions compose just two operations, while seqN does the same thing as Klark's apply function.
It should be said that I'm writing this answer not because I think it is useful to implement things in F# in this way, but as you mentioned railway oriented programming and asked for deeper concepts behind this, it is interesting to see how things can be composed in functional languages.
Can you just apply an array of functions to a given data?
E.g. you can define:
let apply (arg:'a) (fs:(('a->unit) seq)) = fs |> Seq.iter (fun f -> f arg)
Then you will be able to do something like this:
apply 1 [(fun x -> printfn "%d" (x + 1)); (fun y -> printfn "%d" (y + 2))]
I want to apply a function to both members of a homogenous tuple, resulting in another tuple. Following on from my previous question I defined an operator that seemed to make sense to me:
let (||>>) (a,b) f = f a, f b
However, again I feel like this might be a common use case but couldn't find it in the standard library. Does it exist?
I don't think there is any standard library function that does this.
My personal preference would be to avoid too many custom operators (they make code shorter, but they make it harder to read for people who have not seen the definition before). Applying function to both elements of a tuple is logically close to the map operation on lists (which applies a function to all elements of a list), so I would probably define Tuple2.map:
module Tuple2 =
let map f (a, b) = (f a, f b)
Then you can use the function quite nicely with pipelining:
let nums = (1, 2)
nums |> Tuple2.map (fun x -> x + 1)
Given a string of digits, I would like to have a sequence of tuples mapping the non-zero characters with their position in the string. Example:
IN: "000140201"
OUT: { (3, '1'); (4, '4'); (6, '2'); (8, '1') }
Solution:
let tuples = source
|> Seq.mapi (fun i -> fun c -> (i, c))
|> Seq.filter (snd >> (<>) '0')
It seems like (fun i -> fun c -> (i, c)) is a lot more typing than it should be for such a simple and presumably common operation. It's easy to declare the necessary function:
let makeTuple a b = (a, b)
let tuples2 = source
|> Seq.mapi makeTuple
|> Seq.filter (snd >> (<>) '0')
But it seems to me that if the library provides the snd function, it should also provide the makeTuple function (and probably with a shorter name), or at least it should be relatively easy to compose. I couldn't find it; am I missing something? I tried to build something with the framework's Tuple.Create, but I couldn't figure out how to get anything other than the single-argument overload.
But it seems to me that if the library provides the snd function, it should also provide the makeTuple function.
F# assumes that you decompose tuples (using fst, snd) much more often than composing them. Functional library design often follows minimal principle. Just provide functions for common use cases, other functions should be easy to define.
I couldn't find it; am I missing something?
No, you aren't. It's the same reason that FSharpPlus has defined tuple2, tuple3, etc. Here are utility functions straight from Operators:
/// Creates a pair
let inline tuple2 a b = a,b
/// Creates a 3-tuple
let inline tuple3 a b c = a,b,c
/// Creates a 4-tuple
let inline tuple4 a b c d = a,b,c,d
/// Creates a 5-tuple
let inline tuple5 a b c d e = a,b,c,d,e
/// Creates a 6-tuple
let inline tuple6 a b c d e f = a,b,c,d,e,f
I tried to build something with the framework's Tuple.Create, but I couldn't figure out how to get anything other than the single-argument overload.
F# compiler hides properties of System.Tuple<'T1, 'T2> to enforce pattern matching idiom on tuples. See Extension methods for F# tuples for more details.
That said, point-free style is not always recommended in F#. If you like point-free, you have to do a bit of heavy lifting yourself.
The #pad's answer is great, just to add my 2 cents: I am using similar operator
let inline (-&-) a b = (a, b)
and it looks very convenient to write let x = a -&- b
Maybe you'll find this operator useful too