The Claysley composition operator >=>, also known as the βfishβ in Haskell circles, can come in handy in many situations where a set of specialized functions is needed. It works as an operator >>, but instead of compiling simple functions, 'a -> 'bit provides some special properties on them, possibly best expressed as 'a -> m<'b>, where it mis either a monad-like type or some property returns the value of the function. Evidence of this practice in the wider F # community can be found, for example. at Scott Wlaschin Rail Based Programming (Part 2) as a collection of type-returning functions Result<'TSuccess,'TFailure>.
Considering that where there is a binding, there should be a fish, I try to parameterize the canonical definition of the Claysley operator let (>=>) f g a = f a >>= gby the binding function itself:
let mkFish bind f g a = bind g (f a)
This works fine with the caveat that, as a rule, special operators should not be untied by code addressed to the user. I can create functions that return parameters ...
module Option =
let (>=>) f = mkFish Option.bind f
let odd i = if i % 2 = 0 then None else Some i
let small i = if abs i > 10 then None else Some i
[0; -1; 9; -99] |> List.choose (odd >=> small)
// val it : int list = [-1; 9]
... or I can come up with a function application for the two highest values ββof the stack and return the result back without having to refer to the data structure in which I work explicitly:
module Stack =
let (>=>) f = mkFish (<||) f
type 'a Stack = Stack of 'a list
let pop = function
| Stack[] -> failwith "Empty Stack"
| Stack(x::xs) -> x, Stack xs
let push x (Stack xs) = Stack(x::xs)
let apply2 f =
pop >=> fun x ->
pop >=> fun y ->
push (f x y)
, val mkFish : bind:('a -> 'b -> 'c) -> f:('d -> 'b) -> g:'a -> a:'d -> 'c . , ('a ), .
, ?