In Scala there's the notion of a "partial function" that is fairly similar to what F#'s function
keyword allows me to achieve. However Scala's partial functions also allow for composition via the orElse
method as shown below:
def intMatcher: PartialFunction[Any,String] = {
case _ : Int => "Int"
}
def stringMatcher: PartialFunction[Any,String] = {
case _: String => "String"
}
def defaultMatcher: PartialFunction[Any,String] = {
case _ => "other"
}
val msgHandler =
intMatcher
.orElse(stringMatcher)
.orElse(defaultMatcher)
msgHandler(5) // yields res0: String = "Int"
I need to know if there's a way to achieve the same composition functionality in F#.
The way you wrote it in Scala is equivalent to using extension methods in C#. It is not particularly idiomatic to functional programming. To strictly use composable functions in F# you might do something like this.
// reusable functions
let unmatched input = Choice1Of2 input
let orElse f =
function
| Choice1Of2 input -> f input
| Choice2Of2 output -> Choice2Of2 output
let withDefault value =
function
| Choice1Of2 _ -> value
| Choice2Of2 output -> output
// problem-specific functions
let matcher isMatch value x =
if isMatch x then Choice2Of2 value
else Choice1Of2 x
let isInt (o : obj) = o :? int
let isString (o : obj) = o :? string
let intMatcher o = matcher isInt "Int" o
let stringMatcher o = matcher isString "String" o
// composed function
let msgHandler o =
unmatched o
|> orElse intMatcher
|> orElse stringMatcher
|> withDefault "other"
Here, Choice1Of2
means that we haven't found a match yet and contains the unmatched input. And Choice2of2
means we found a match and contains the output value.