Array of 'a option - f#

I have a function
foo 'a -> 'b option
and I have a n array of 'a
let data_in: 'a[] = ...
I need to get array of 'b. So I have two question:
I want to do something like this:
bar(data: 'a []) : 'b [] =
data |> foo
let result : 'b[] = Array.filter (fun e ->
match e with
| Some(e) -> true
| None -> false)
but I get the error that bar expected type 'b, but get 'b option. How can I fix the type declaration in bar ?
May be there is a way to do all this without map + filter by one expression ?

Array.choose does map + filter in one go.
It is probably the easiest solution for your problem.

Related

final output of Result, in F#

This seems like a question that has an ultra simple answer, but I can't think of it:
Is there a built in method, within Result, for:
let (a: Result<'a, 'a>) = ...
match a with
| Ok x -> x
| Error e -> e
No, because this function requires the Ok type and the Error type to be the same, which makes Result less general.
No, there isn't any function which will allow you to do so. But you can easily define it:
[<RequireQualifiedAccess>]
module Result =
let join (value: Result<'a, 'a>) =
match value with
| Ok v -> v
| Error e -> e
let getResult s =
if System.String.IsNullOrEmpty s then
Error s
else
Ok s
let a =
getResult "asd"
|> Result.join
|> printfn "%s"
It doesn't make Result less general (as said by #brianberns), because it's not an instance member. Existence of Unwrap doesn't make Task less general
Update
After more scrupulous searching inside FSharpPlus and FSharpx.Extras I've found necessary function. It's signature ('a -> 'c) -> ('b -> 'c) -> Result<'a,'b> -> c instead of Result<'a, 'a> -> 'a and it's called Result.either in both libraries (source 1 and source 2). So in order to get value we may pass id as both parameters:
#r "nuget:FSharpPlus"
open FSharpPlus
// OR
#r "nuget:FSharpx.Extras"
open FSharpx
getResult "asd"
|> Result.either id id
|> printfn "%s"
Also it's may be useful to define shortcut and call it Result.join or Result.fromEither as it's called in Haskell

F# type inference of generic type arguments with numeric suffix?

While playing around with map, apply and such to better understand them, the inferred generic types on the following code turned out not be what I expected, but the code still works:
Note: the // comments are written by me so I can show them, but they are the exact copy of the auto annotations printed by Ionide.
let map2 fOk fErr (a : Result<'a,'e>) (b : Result<'b,'e>)= // ('a -> 'b -> 'a0) -> ('e -> 'e -> 'e) -> Result<'a,'e> -> Result<'b,'e> -> Result<'a,'e>
match a, b with
| Ok aOk, Ok bOk -> fOk aOk bOk |> Ok
| Error aErr, Error bErr -> fErr aErr bErr |> Error
| Error aErr, _ -> Error aErr
| _, Error bErr -> Error bErr
let lift2ResultFromMap2 f= // ('a -> 'b -> 'c) -> (Result<'a,'d list> -> Result<'b,'d list> -> Result<'c,'d list>)
map2 f List.append
Here I expected that the return type of map2 is Result<'a0,'e> instead of Result<'a,'e>.
But then when I use it in defining lift2ResultFromMap2 the return type is exactly what I expect, Result<'c,'d list> instead of Result<'a,'d list> that map2 would suggest.
Am I right to think this is an IDE bug? or is there some additional wildcard like meaning to the numbered suffix?
Your constraints are respected first.
Now for your example, it tried to pick 'a for the first unconstrained value, which is the return type of fOk, saw 'a was already in use, so it went with 'a0. So, if you let it pick the constraints with:
(a : Result<_,'e>) (b : Result<_,'e>)
fOk will be inferred to be 'a -> 'b -> 'c. If you have enough values to infer up to 'e, you'll end up seeing an 'e0.

Name for function like Option.bind that returns Some(x) when input is None

The normal Option.bind function is defined like this:
// ('T -> 'U option) -> 'T option -> 'U option
let bind f x =
match x with
| None -> None
| Some x' -> f x'
I am in need of a slightly different version of this:
// ('T -> 'U -> 'U option) -> 'T option -> ('U -> 'U option)
let myBind f x =
match x with
| None -> Some
| Some x' -> f x'
Does this function have a standard name? (If not I'll gladly accept concise suggestions.)
For interested readers, my usecase is this: I have a business object (say Order) I want to apply a constraint to (order date, customer, etc.). The functions that apply constraints to e.g. an Order have signature 'Constraint -> Order -> Order option. They return Some order if the order passed the constraint, and None otherwise (and can thus be composed using Option.bind). Now, if the constraint is None, it's essentially a no-op and Some order should be returned. Instead of having all constraint functions accept 'Constraint option I can factor out this part of the logic using the function above (which then need to be applied during composition).
I originally called the function something like bindConstraint, but it's completely generic and really has nothing to do with my usecase (ref. Mark Seemann's article on the topic). Due to its similarity with bind I wondered if there is a standard name for this.
Let's look at your function type signature:
// ('T -> 'U -> 'U option) -> 'T option -> ('U -> 'U option)
The 'U -> 'U option type can actually be factored out of that signature. Let's call that type 'V. Then the type signature becomes:
// ('T -> 'V) -> 'T option -> 'V
Which looks rather similar to Option.map, whose signature is:
// ('T -> 'V) -> 'T option -> 'V option
So basically, your function is equivalent to Option.map followed by a defaultArg to turn that 'V option into a 'V (supplying a default value if the option was None).
So I'd probably call it something like defaultMap or mapDefault.
hmmm...
I was wondering if you factor out the 'U, that you end up working inside a reader monad, and then your function IS option.bind there's nothing to do!
'U -> .....('T -> 'U option) -> 'T option -> 'U option
i.e. this is a constraint on string?
let longerThan : int -> string -> string option =
fun i s ->
if (String.length s > i) then
Some s
else
None
and this is you using myBind
let foo = myBind longerThan (Some 1)
but this is the code without myBind
let bar =
fun s ->
(Some 1) |> Option.bind (fun i -> longerThan i s)
we've just factored out the 'U and we write our code inside a function.
(my code looks more complex because we've written longer than to work nicely with your bind, if we swap the parameter order, then your version looks more complex than mine)
my other observation is if you are just doing constraints, then isn't using
'U -> bool
a bit simpler?...and then you just use "where"...(can you do this in a computational expression?...you can in LINQ I think).
P.S.
actually the semantics of your code Is different...you want None to be interpreted as the identity map....
so actually I think in your world I would operate on the constraint directly
type Constraint<'a> = 'a -> 'a option
let applyConstraint : Constraint<'a> option -> 'a -> 'a option =
function
| None -> Some
| Some f -> f
and then simply compose constraints;
let compose : Constraint<'a> -> Constraint<'a> -> Constraint<'a> =
fun c1 c2 -> fun a -> Option.bind c2 (c1 a)
(though I may have c1 and c2 the wrong way around)

F# Matching on possible generic list or sequence types

I am trying figure out if a generic type wrapped in a rop result is a list or not. This is what I tried but I got errors.
let checkType (result : RopResult<'tSuccess, 'errors>) =
match result with
| Success (s, msg) ->
match s with
| :? [] -> // error here
Sample
let isList<'s> () = true
let processList (ls : 'domain list) = true
let processType (s : 'domain) = true
let checkType (result : RopResult<'tSuccess, 'errors>) =
match result with
| Success (s, msg) ->
match s with
| s when isList<s>() -> processList s
| _ -> processType s
| Failure (x) -> false
I'll first explain the technicalities of how to get your code to work, and then try to convince you (as the other folks on this thread) that it may not be the right way to approach your problem.
Firstly, your match statement has a syntax error. You would write the type test and the cast in one swoop as
match s with
| :? List<int> as theIntList -> ...do something with theIntList ...
When you add that to your code, the F# compiler will complain "The runtime coercion or type test ... involves an indeterminate type. ... Further type annotations are needed". Fix that by being more specific about what kind of result your checkType is processing: it is some System.Object instance and the message, so you'd write:
let checkType (result : Result<obj*string, 'errors>) =
match result with
| Success (s, msg) ->
match s with
| :? List<int> as theIntList -> ... do something
Note that you can't change that to a generic thing like List<_> - F# will do the type test and the cast in one go, and would not hence know what to cast to. If you try to, you will see warnings that your List<_> has been inferred to be List<obj>
Having said all that: Using obj is not the idiomatic way to go, as others have tried to point out already. The answers of #robkuz and #TheInnerLight contain all you need: A map function, functions that operate on individual result types, which then becomes nicely composable:
let map f x =
match x with
| Success (s, msg) -> Success (f s, msg)
| Failure f -> Failure f
// This will automatically be inferred to be of type Result<(int list * string), 'a>
let myFirstResult = Success ([1;2], "I've created an int list")
// This will automatically be inferred to be of type Result<(string list * string), 'a>
let mySecondResult = Success (["foo"; "bar"], "Here's a string list")
// Process functions for specific result types. No type tests needed!
let processIntList (l: int list) = Seq.sum l
let processStringList = String.concat "; "
// This will automatically be inferred to be of type Result<(int * string), 'a>
let mapFirst = myFirstResult |> map processIntList
// This will automatically be inferred to be of type Result<(string * string), 'a>
let mapSecond = mySecondResult |> map processStringList
I am not sure if I really understand your problem.
In general if you have some polymorphic type (like your RopResult) and you want to process the polymorphic part of it a good approach in F# would be
to disentagle your code into a wrapper code and a processor code where your processor code is delivered via a higher order function for the processing part.
Example:
type RopResult<'tSuccess, 'tError> =
| Success of 'tSuccess
| Error of 'tError
let checkType (process: 'tSuccess -> 'tResult) (result : RopResult<'tSuccess, 'tError>) =
match result with
| Success s -> process s |> Success
| Error e -> Error e
and
let processList (ls : 'domain list) = true
let processType (s : 'domain) = true
and then you
checkType processList aListWrappedInResult
checkType processType aTypeWrappedInResult
Assuming you wanted to determine whether a supplied value was of a generic list type, you could do this:
let isList value =
let valueType = value.GetType()
match valueType.IsGenericType with
|true -> valueType.GetGenericTypeDefinition() = typedefof<_ list>
|false -> false
Example usage:
isList [5];;
val it : bool = true
isList ["a", "b"];;
val it : bool = true
isList "a";;
val it : bool = false
When working with something like RopResult, or more formally, Either, it's helpful to define the map function. The map function takes a function 'a -> 'b and gives you a function which operates in some elevated domain, e.g. RopResult<'a,'c> -> RopResult<'b,'c>.
This is analogous to List.map : ('a ->'b) -> 'a List -> 'b List.
We define it like this:
let map f v =
match v with
|Success sv -> Success (f sv)
|Failure fv -> Failure (fv)
You can then use isList on RopResults by simply doing:
ropResult |> map isList
Others here are warning you in the comments that there may be potential issues surrounding how you actually process the results once you've determined whether the type is a list or not. Specifically, you will need to ensure that the return types of your processList and processType functions are the same (although I would recommend revisiting the naming of processType and call it processValue instead. Since you are not operating on the type, I think the name is confusing).

F# Equivalent to Enumerable.OfType<'a>

...or, how do I filter a sequence of classes by the interfaces they implement?
Let's say I have a sequence of objects that inherit from Foo, a seq<#Foo>. In other words, my sequence will contain one or more of four different subclasses of Foo.
Each subclass implements a different independent interface that shares nothing with the interfaces implemented by the other subclasses.
Now I need to filter this sequence down to only the items that implement a particular interface.
The C# version is simple:
void MergeFoosIntoList<T>(IEnumerable<Foo> allFoos, IList<T> dest)
where T : class
{
foreach (var foo in allFoos)
{
var castFoo = foo as T;
if (castFoo != null)
{
dest.Add(castFoo);
}
}
}
I could use LINQ from F#:
let mergeFoosIntoList (foos:seq<#Foo>) (dest:IList<'a>) =
System.Linq.Enumerable.OfType<'a>(foos)
|> Seq.iter dest.Add
However, I feel like there should be a more idiomatic way to accomplish it. I thought this would work...
let mergeFoosIntoList (foos:seq<#Foo>) (dest:IList<'a>) =
foos
|> Seq.choose (function | :? 'a as x -> Some(x) | _ -> None)
|> Seq.iter dest.Add
However, the complier complains about :? 'a - telling me:
This runtime coercion or type test from type 'b to 'a involves an indeterminate type based on information prior to this program point. Runtime type tests are not allowed on some types. Further type annotations are needed.
I can't figure out what further type annotations to add. There's no relationship between the interface 'a and #Foo except that one or more subclasses of Foo implement that interface. Also, there's no relationship between the different interfaces that can be passed in as 'a except that they are all implemented by subclasses of Foo.
I eagerly anticipate smacking myself in the head as soon as one of you kind people points out the obvious thing I've been missing.
You can do this:
let foos = candidates |> Seq.filter (fun x -> x :? Foo) |> Seq.cast<Foo>
Typically just adding a 'box' is sufficient (e.g. change function to fun x -> match box x with), but let me try it out...
Yeah; basically you cannot sideways cast from one arbitrary generic type to another, but you can upcast to System.Object (via box) and then downcast to anything you like:
type Animal() = class end
type Dog() = inherit Animal()
type Cat() = inherit Animal()
let pets : Animal list =
[Dog(); Cat(); Dog(); Cat(); Dog()]
printfn "%A" pets
open System.Collections.Generic
let mergeIntoList (pets:seq<#Animal>) (dest:IList<'a>) =
pets
|> Seq.choose (fun p -> match box p with
| :? 'a as x -> Some(x) | _ -> None) //'
|> Seq.iter dest.Add
let l = new List<Dog>()
mergeIntoList pets l
l |> Seq.iter (printfn "%A")
From https://gist.github.com/kos59125/3780229
let ofType<'a> (source : System.Collections.IEnumerable) : seq<'a> =
let resultType = typeof<'a>
seq {
for item in source do
match item with
| null -> ()
| _ ->
if resultType.IsAssignableFrom (item.GetType ())
then
yield (downcast item)
}
Another option for those inclined:
Module Seq =
let ofType<'a> (items: _ seq)= items |> Seq.choose(fun i -> match box i with | :? 'a as a -> Some a |_ -> None)
I have an open source library available on nuget, FSharp.Interop.Compose
That Converts most Linq methods into a idomatic F# form. Including OfType
Test Case:
[<Fact>]
let ofType () =
let list = System.Collections.ArrayList()
list.Add(1) |> ignore
list.Add("2") |> ignore
list.Add(3) |> ignore
list.Add("4") |> ignore
list
|> Enumerable.ofType<int>
|> Seq.toList |> should equal [1;3]

Resources