Map on Map<'a, int> - f#

I have the following type :
type MultiSet<'a when 'a: comparison> = MSet of Map<'a, int>
and I now want to declare af map function for this type with the signature :
('a -> 'b) -> Multiset<'a> -> Multiset<'b> when 'a : comparison and 'b : comparison
I have tried :
let map m ms =
match ms with
| MSet s -> MSet ( Map.map (fun key value -> m key) s )
But that it has the signature :
('a -> int) -> Multiset<'a> -> Multiset<'a> when 'a : comparison
What is wrong with my implementation when I want the first mentioned function signature?

Map.map maps values, not keys. And with good reason: it can't just go and plug the mapped keys instead of the original ones - they might not fit. Heck, they might not even be unique for all Map.map knows!
If you want to construct a map with different keys, you'll have to take it apart as a sequence, convert it, then construct another Map from it:
let map m (MSet s) =
MSet ( Map.ofSeq <| seq { for KeyValue (key, value) in s -> m key, value } )
This implementation has your required signature.
(also, notice how you don't have to do match, you can include the pattern right in parameter declaration)
Beware that this implementation does nothing for validating the new keys: for example, if they turn out to be non-unique, some counts will be lost. I leave this as an exercise for the reader.

Related

F# How to write a function that takes int list or string list

I'm messing around in F# and tried to write a function that can take an int list or a string list. I have written a function that is logically generic, in that I can modify nothing but the type of the argument and it will run with both types of list. But I cannot generically define it to take both.
Here is my function, without type annotation:
let contains5 xs =
List.map int xs
|> List.contains 5
When I try to annotate the function to take a generic list, I receive a warning FS0064: the construct causes the code to be less generic than indicated by the type annotations. In theory I shouldn't need to annotate this to be generic, but I tried anyway.
I can compile this in two separate files, one with
let stringtest = contains5 ["1";"2";"3";"4"]
and another with
let inttest = contains5 [1;2;3;4;5]
In each of these files, compilation succeeds. Alternately, I can send the function definition and one of the tests to the interpreter, and type inference proceeds just fine. If I try to compile, or send to the interpreter, the function definition and both tests, I receive error FS0001: This expression was expected to have type string, but here has type int.
Am I misunderstanding how typing should work? I have a function whose code can handle a list of ints or a list of strings. I can successfully test it with either. But I can't use it in a program that handles both?
You are running into value restrictions on the automatic generalization of the type inference system as outlined here
Specifically,
Case 4: Adding type parameters.
The solution is to make your function generic rather than just making its parameters generic.
let inline contains5< ^T when ^T : (static member op_Explicit: ^T -> int) > (xs : ^T list) =
List.map int xs
|> List.contains 5
You have to make the function inline because you have to use a statically resolved type parameter, and you have to use a statically resolved type parameter in order to use member constraints to specify that the type must be convertible to an int. As outlined here
You can use inline to prevent the function from being fixed to a particular type.
In FSI, the interactive REPL:
> open System;;
> let inline contains5 xs = List.map int xs |> List.contains 5;;
val inline contains5 :
xs: ^a list -> bool when ^a : (static member op_Explicit : ^a -> int)
> [1;2;3] |> contains5;;
val it : bool = false
> ["1";"2";"5"] |> contains5;;
val it : bool = true
Note that the signature of contains5 has a generic element to it. There's more about inline functions here.
This is already answered correctly above, so I just wanted to chime in with why I think it's a good thing that F# appears to makes this difficult / forces us to lose type safety. Personally I don't see these as logically equivalent:
let inline contains5 xs = List.map int xs |> List.contains 5
let stringTest = ["5.00"; "five"; "5"; "-5"; "5,"]
let intTest = [1;2;3;4;5]
contains5 stringTest // OUTPUT: System.FormatException: Input string was not in a correct format.
contains5 intTest // OUTPUT: true
When inlined, the compiler would create two logically distinct versions of the function. When performed on the list<int> we get a boolean result. When performed on a list<string> we get a boolean result or an exception. I like that F# nudges me towards acknowledging this.
let maybeInt i =
match Int32.TryParse i with
| true,successfullyParsedInteger -> Some successfullyParsedInteger
| _ -> None
let contains5 xs =
match box xs with
| :? list<int> as ixs ->
ixs |> List.contains 5 |> Ok
| :? list<string> as sxs ->
let successList = sxs |> List.map maybeInt |> List.choose id
Ok (successList |> List.contains 5)
| _ ->
Error "Error - this function expects a list<int> or a list<string> but was passed something else."
let stringTest = ["5.00"; "five"; "5"; "-5"; "5,"]
let intTest = [1;2;3;4;5]
let result1 = contains5 stringTest // OUTPUT: Ok true
let result2 = contains5 intTest // OUTPUT: Ok true
Forces me to ask if some of the values in the string list cannot be parsed, should I drop out and fail, or should I just try and look for any match on any successful parse results?.
My approach above is horrible. I'd split the function that operates on the strings from the one that operates on the integers. I think your question was academic rather than a real use case though, so I hope I haven't gone off on too much of a tangent here!
Disclaimer: I'm a beginner, don't trust anything I say.

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)

Type definitions and type inference in F#

I have two example types, defined in this order:
type Quote = {QuoteNum: decimal option; ShipToID: decimal option}
type Sales = {SalesNum: decimal option; ShipToID: decimal option}
and I'm trying to write a function that can accept a both types:
let fx (y: Map<decimal option, _ list>) =
y
|> Map.map (fun key list -> list
|> List.map (fun x -> x.ShipToID))
When I try to pass a Map<decimal option, Quote list> to the function, I get an error:
Type mismatch. Expecting a
Map<decimal option,Sales list>
but given a
Map<decimal option,Quote list>
I would have thought that I'd be able to pass a map of both types to the function, but the compiler seems to be inferring that only a Map<decimal option, Sales list> is acceptable to the function. I suspect that the compiler "sees" the Sales type most recently and assumes that that's what the function needs. I thought I had made the function relatively generic by including the _ in the type annotation.
How can I make the function accept both types? Can I do this without redefining the types themselves?
Your suspicions are correct. F# needs to infer a single concrete type there, so will use the most recent matching type it finds.
You can make it work by defining an interface with ShipToID field and have both types implement it (not sure if that counts as redefining the types for you), or by providing a getter function for extracting the field value (which would let you keep the function generic):
let fx (shipToIdGetter: 'a -> decimal option) (y: Map<decimal option, 'a list>) =
y
|> Map.map (fun key list ->
list
|> List.map (fun x -> shipToIdGetter x))
Your code would work as written if F# supported row polymorphism (which happens to be the case for OCaml).
While I believe that scrwtp's answer is the way to go, you also have the choice to use inline and member constraints (or static duck typing...if thats a valid term). For the sake of completeness:
type Quote = {QuoteNum: decimal option; ShipToID: decimal option}
type Sales = {SalesNum: decimal option; ShipToID: decimal option}
let inline fx (y: Map<decimal option, 'a list>) =
let inline getId x = ( ^a : (member ShipToID : decimal option) x)
y |> Map.map (fun key list -> list |> List.map getId)
let q : Quote = { QuoteNum = None; ShipToID = None}
let s : Sales = { SalesNum = None; ShipToID = None}
fx <| Map.ofList [ None, [q]]
fx <| Map.ofList [ None, [s]]
The getId function uses the rather obscure syntax to call the ShipToID member based on ^a's expected structure.

How to interpret a function signature

I am still confused on how to read function signatures.
The Option.map signature is the following:
/// map f inp evaluates to match inp with None -> None | Some x -> Some (f x).
/// mapping: A function to apply to the option value.
/// option: The input option.
val map : mapping:('T -> 'U) -> option:'T option -> 'U option
However, I have no clue what that signature means.
I read it as the following:
There's a function called map that takes a function as an input that we'll call "mapping" and it will yield a result that is also a function that we'll call "option".
Mapping Parameter:
mapping:('T -> 'U)
The function that we pass in as input takes Titanium (i.e. 'T) as the input and yields Uranium (i.e. 'U) as output.
The Option returned
option:'T option -> 'U option
We'll call the output of the map function "option".
Thus, this "option" that is returned from executing the map function is also a function as referenced above. It's takes a Titanium option and yields a Uranium option.
Example:
type String20 = String20 of string
type Name = { First:String20
Last:String20
Suffix:String20 option }
let tryCreateName (first:string) (last:string) (suffix:string option) =
let isValid = [first; last]
|> List.forall (fun x -> x.Length > 2 && x.Length <= 20)
if isValid then
Some { First = String20(first);
Last = String20(last);
Suffix = Option.map String20 suffix }
else None
How does the following expression map:
Option.map String20 suffix
Based on the expression above, where is the "returned function" of Titanium option -> Uranium option?
First off take a look at Option.map<'T,'U> Function (F#) and notice
The expression map f inp evaluates to match inp with None -> None |
Some x -> Some (f x).
So lets convert this comment to working code. First map is a method of the type Option, but to make it easier we will make it a function outside of a type and to avoid conflicts with other map functions we will give it the name OptionMap.
let OptionMap = f inp =
match inp with
| None -> None
| Some x -> Some (f x)
Now to get the signature of this function just send it to F# Interactive
val OptionMap : f:('a -> 'b) -> inp:'a option -> 'b option
and to make the types obvious we will type the parameters of the function.
let optionMap (f : ('a -> 'b)) (inp : 'a option) : 'b option =
match inp with
| None -> None
| Some x -> Some (f x)
Now to test this we can use
let (test : String20 option) = optionMap String20 (Some("something"))
printfn "test: %A" test
// test: Some (String20 "something")
So what happened in OptionMap that allowed this to work
If we add some print statements let sees what happens
let optionMap (f : ('a -> 'b)) (inp : 'a option) : 'b option =
printfn "f: %A" f
printfn "inp: %A" inp
match inp with
| None -> None
| Some x ->
let result = Some (f x)
printfn "result: %A" result
result
we get
f: <fun:test#63>
inp: Some "something"
result: Some (String20 "something")
we see that f is a function which is String20
So how can String20 be a function?
If we send String20 to F# Interactive it gives.
> String20;;
val it : arg0:string -> String20 = <fun:clo#4>
So String20 is a function that takes a string and returns a type of String20. That smells of a constructor.
Let's test that out in F# interactive.
> let test1 = String20 "something";;
val test1 : String20 = String20 "something"
Sure enough, String20 is a constructor, but we didn't specifically create a constructor as is done in the Object-Oriented world.
You have to think of a type, even a discriminated union as having constructors. The constructors are not specifically written but do exist. So String20 is a constructor that takes one value, a string, which is a function with the correct type signature for the Option.map function.
I gave the answer a lot more detail so that one can learn a process on how to break down problems and look at the inner workings as a tool to solving these kinds of problems.
To learn more about the lower level details of how functional programming works one needs to understand lambda calculus. The best way I know to learn it is to read An Introduction To Functional Programming Through Lambda Calculus by Greg Michaelson and look at the info in the lambda calculus tag.
Also if you like the book, you should buy a copy instead of using the free version.
There are two ways of looking at it.
let f x y = x + y
// val f: x:int -> y:int -> int
One way is to say that function f takes two parameters, x of type int and y of type int, and returns an int. So I can supply two arguments and get the result:
let a = f 4 5
// val a: int = 9
The other way is that the function takes one parameter, x of type int, and returns another function, which takes one parameter, y of type int, and returns an int. So I can supply one argument and get a function as result:
let b = f 4
// val b: int -> int
Mathematically, it's always the second way - all functions are one-parameter functions. This notion is very convenient for programming with higher-order functions.
But the first way is usually more understandable to humans, so you will often see functions discussed as if they take multiple parameters.
String20 is the case constructor for the String20 Discriminated Union case. It's a function with the type string -> String20. So string takes the place of 'T, and String20 takes the place of 'U in the mapping you supply to Option.map.
Generally, if you have a function T1 -> T2 -> ... and you apply it to one parameter, you get a function T2 -> .... In the case of Option.map, T1 is itself a function, but that is of no consequence to the way the arguments are applied.
I find it confusing to call a function "option", a string "Titanium" and a type called String20 "Uranium", so I'll stick with type names.
You ask where the "returned function" that maps a string option to a String20 option is in the expression Option.map String20 suffix. It is simply
Option.map String20
Since String20 constructs a String20 from a string, Option.map String20 is a function that maps a string to a String20 if it is present, and to None otherwise.
If you write Option.map String20 suffix, this function is applied to suffix, which would be a string option. The result of this expression is a String20 option.

How to downcast from obj to option<obj>?

I have a function that takes a parameter of type object and needs to downcast it to an option<obj>.
member s.Bind(x : obj, rest) =
let x = x :?> Option<obj>
If I pass (for example) an Option<string> as x, the last line throws the exception: Unable to cast object of type 'Microsoft.FSharp.Core.FSharpOption'1[System.String]' to type 'Microsoft.FSharp.Core.FSharpOption'1[System.Object]'.
Or, if I try a type test:
member s.Bind(x : obj, rest) =
match x with
| :? option<obj> as x1 -> ... // Do stuff with x1
| _ -> failwith "Invalid type"
then x never matches option<obj>.
In order to make this work, I currently have to specify the type the option contains (e.g. if the function is passed an option<string>, and I downcast the parameter to that rather than option<obj>, the function works.
Is there a way I can downcast the parameter to option<obj> without specifying what type the option contains? I've tried option<_>, option<#obj>, and option<'a> with the same results.
By way of background, the parameter needs to be of type obj because I'm writing an interface for a monad, so Bind needs to bind values of different types depending on the monad that implements the interface. This particular monad is a continuation monad, so it just wants to make sure the parameter is Some(x) and not None, then pass x on to rest. (The reason I need the interface is because I'm writing a monad transformer and I need a way to tell it that its parameter monads implement bind and return.)
Update: I managed to get around this by upcasting the contents of the option before it becomes a parameter to this function, but I'm still curious to know if I can type-test or cast an object (or generic parameter) to an option without worrying about what type the option contains (assuming of course the cast is valid, i.e. the object really is an option).
There isn't any nice way to solve this problem currently.
The issue is that you'd need to introduce a new generic type parameter in the pattern matching (when matching against option<'a>), but F# only allows you to define generic type parameters in function declarations. So, your only solution is to use some Reflection tricks. For example, you can define an active pattern that hides this:
let (|SomeObj|_|) =
let ty = typedefof<option<_>>
fun (a:obj) ->
let aty = a.GetType()
let v = aty.GetProperty("Value")
if aty.IsGenericType && aty.GetGenericTypeDefinition() = ty then
if a = null then None
else Some(v.GetValue(a, [| |]))
else None
This will give you None or Some containing obj for any option type:
let bind (x : obj) rest =
match x with
| SomeObj(x1) -> rest x1
| _ -> failwith "Invalid type"
bind(Some 1) (fun n -> 10 * (n :?> int))
I am not certain why you need to get your input as obj, but if your input is an Option<_>, then it is easy:
member t.Bind (x : 'a option, rest : obj option -> 'b) =
let x = // val x : obj option
x
|> Option.bind (box >> Some)
rest x
To answer your last question: you can use a slight variation of Tomas' code if you need a general-purpose way to check for options without boxing values beforehand:
let (|Option|_|) value =
if obj.ReferenceEquals(value, null) then None
else
let typ = value.GetType()
if typ.IsGenericType && typ.GetGenericTypeDefinition() = typedefof<option<_>> then
let opt : option<_> = (box >> unbox) value
Some opt.Value
else None
//val ( |Option|_| ) : 'a -> 'b option
let getValue = function
| Option x -> x
| _ -> failwith "Not an option"
let a1 : int = getValue (Some 42)
let a2 : string = getValue (Some "foo")
let a3 : string = getValue (Some 42) //InvalidCastException
let a4 : int = getValue 42 //Failure("Not an option")

Resources