问题
I have a validation module copied from Railway oriented programming that performs error handling in my application:
type ErrorMessage = ErrorMessage of string
type ValidationResult<'T> =
| Success of 'T
| Error of ErrorMessage
module ValidationResult =
let doubleMap successHandler errorHandler = function
| Success x -> successHandler x
| Error e -> errorHandler e
let bind f = function
| Success x -> f x
| Error e -> Error e
let (>=>) f g = f >> bind g
I was testing the Kleisli composition by using the following test functions:
let validation1 (list: int list) =
if List.length list = 6
then Success list
else Error <| ErrorMessage "Length error"
let validation2 list =
if List.forall (fun x -> x > 6) list
then Success list
else Error <| ErrorMessage "All elements must be larger than 6"
let combined = validation1 >=> validation2
//^^^^^^^^^^^^ compile error
To my understanding, validation1
and validation2
should compose because both are of type int list -> ValidationResult<int list>
. However I got a compile error
Expecting a type supporting the operator '>=>' but given a function type. You may be missing an argument to a function.
How can I solve this?
回答1:
It seems that you simply forgot to open ValidationResult
, so your composition operator is not in scope.
For a normal function, F# would have complained that the symbol was undefined. But operators are a different matter.
Operators can be defined in two ways: as a standalone function (the functional way) or as a static member on one of the types passed to the operator (the .NET way). In the former case, the function needs to be visible in scope, but in the latter case it doesn't: as long as you managed to get hold of an object with an operator defined as static member, you don't need to have its type visible.
This is why F# says that it "expected a type supporting operator" instead of "function is undefined".
来源:https://stackoverflow.com/questions/35822772/compile-error-for-kleisli-composition