Generic Equals implementation - f#

I have several generic equality functions, which are used when overriding Object.Equals:
type IEqualityComparer<'T> = System.Collections.Generic.IEqualityComparer<'T>
let equalIf f (x:'T) (y:obj) =
if obj.ReferenceEquals(x, y) then true
else
match box x, y with
| null, _ | _, null -> false
| _, (:? 'T as y) -> f x y
| _ -> false
let equalByWithComparer (comparer:IEqualityComparer<_>) f (x:'T) (y:obj) =
(x, y) ||> equalIf (fun x y -> comparer.Equals(f x, f y))
Typical usage would be:
type A(name) =
member __.Name = name
override this.Equals(that) =
(this, that) ||> equalByWithComparer StringComparer.InvariantCultureIgnoreCase (fun a -> a.Name)
type B(parent:A, name) =
member __.Parent = parent
member __.Name = name
override this.Equals(that) = (this, that) ||> equalIf (fun x y ->
x.Parent.Equals(y.Parent) && StringComparer.InvariantCultureIgnoreCase.Equals(x.Name, y.Name))
I'm mostly happy with this. It reduces boilerplate[wikipedia]. But I'm annoyed having to use equalBy instead of the more concise equalByWithComparer in type B (since its equality depends on its parent's).
It feels like it should be possible to write a function that accepts a reference to the parent (or 0..N projections), which are checked for equality using Equals, along with a property to be checked and its accompanying comparer, but I've yet been unable imagine its implementation. Perhaps all this is overdone (not sure). How might such a function be implemented?
EDIT
Based on Brian's answer, I came up with this, which seems to work okay.
let equalByProjection proj (comparer:IEqualityComparer<_>) f (x:'T) (y:obj) =
(x, y) ||> equalIf (fun x y ->
Seq.zip (proj x) (proj y)
|> Seq.forall obj.Equals && comparer.Equals(f x, f y))
type B(parent:A, otherType, name) =
member __.Parent = parent
member __.OtherType = otherType //Equals is overridden
member __.Name = name
override this.Equals(that) =
(this, that) ||> equalByProjection
(fun x -> [box x.Parent; box x.OtherType])
StringComparer.InvariantCultureIgnoreCase (fun b -> b.Name)

Another implementation, based on Brian's suggestion:
open System
open System.Collections.Generic
// first arg is always 'this' so assuming that it cannot be null
let rec equals(a : 'T, b : obj) comparisons =
if obj.ReferenceEquals(a, b) then true
else
match b with
| null -> false
| (:? 'T as b) -> comparisons |> Seq.forall(fun c -> c a b)
| _ -> false
// get values and compares them using obj.Equals
//(deals with nulls in both positions then calls <first arg>.Equals(<second arg>))
let Eq f a b = obj.Equals(f a, f b)
// get values and compares them using IEqualityComparer
let (=>) f (c : IEqualityComparer<_>) a b = c.Equals(f a, f b)
type A(name) =
member __.Name = name
override this.Equals(that) =
equals (this, that) [
(fun x -> x.Name) => StringComparer.InvariantCultureIgnoreCase
]
type B(parent:A, name) =
member __.Parent = parent
member __.Name = name
override this.Equals(that) =
equals(this, that) [
Eq(fun x -> x.Parent)
(fun x -> x.Name) => StringComparer.InvariantCultureIgnoreCase
]

Are you just looking for something that takes e.g.
[
(fun x -> x.Parent), (fun a b -> a.Equals(b))
(fun x -> x.Name), (fun a b -> SC.ICIC.Equals(a,b))
]
where you have the list of (projection x comparer) to run on the object? (Probably will need more type annotations, or clever pipelining.)

Just to satisfy Daniel's curiosity, here's how to encode the existential type
exists 'p. ('t -> 'p) * ('p -> 'p -> bool)
in F#. Please don't up-vote this answer! It's too ugly to recommend in practice.
The basic idea is that the existential type above is roughly equivalent to
forall 'x. (forall 'p. ('t -> 'p) * ('p -> 'p -> bool) -> 'x) -> 'x
because the only way that we could implement a value of this type is if we really have an instance of ('t -> 'p) * ('p -> 'p -> bool) for some 'p that we can pass to the first argument to get out a return value of the arbitrary type 'x.
Although it looks more complicated than the original type, this latter type can be expressed in F# (via a pair of nominal types, one for each forall):
type ProjCheckerUser<'t,'x> =
abstract Use : ('t -> 'p) * ('p -> 'p -> bool) -> 'x
type ExistsProjChecker<'t> =
abstract Apply : ProjCheckerUser<'t,'x> -> 'x
// same as before
let equalIf f (x:'T) (y:obj) =
if obj.ReferenceEquals(x, y) then true
else
match box x, y with
| null, _ | _, null -> false
| _, (:? 'T as y) -> f x y
| _ -> false
let checkAll (l:ExistsProjChecker<_> list) a b =
// with language support, this could look more like:
// let checkProj (ExistsProjChecker(proj,check)) = check (proj a) (proj b)
// l |> List.forall checkProj
let checkProj = {new ProjCheckerUser<_,_> with
member __.Use(proj,check) = check (proj a) (proj b) }
l |> List.forall
(fun ex -> ex.Apply checkProj)
let fastIntCheck (i:int) j = (i = j)
let fastStringCheck (s:string) t = (s = t)
type MyType(id:int, name:string) =
static let checks =
// with language support this could look more like:
// [ExistsProjChecker((fun (t:MyType) -> t.Id, fastIntCheck)
// ExistsProjChecker((fun (t:MyType) -> t.Name, fastStringCheck)]
[{ new ExistsProjChecker<MyType> with
member __.Apply u = u.Use ((fun t -> t.Id), fastIntCheck) }
{ new ExistsProjChecker<MyType> with
member __.Apply u = u.Use ((fun t -> t.Name), fastStringCheck) }]
member x.Id = id
member x.Name = name
override x.Equals(y) =
equalIf (checkAll checks) x y
As you can see, the lack of language support results in a lot of boilerplate (basically all of the object creation expressions, calls the the method Use and Apply), which makes this approach unattractive.

Related

match by value in a discriminated union, in F#

with this union:
type T =
| A
| B
| C
and a T list
I would like to implement something like this pseudo code:
let countOfType (t: Type) (l: T list) =
l
|> List.filter (fun x -> x.GetType() = t)
|> List.length
when I would pass if I want to count the 'A', 'B', etc..
but A.GetType() and B.GetType() return the T type, so this doesn't work.
Is there a way where I could check the type by passing it as a parameter?
The practical case here is that I have a Map that gets updated every few seconds and its values are part of the same DU. I need to be able to see how many of each type, without having to update the code (like a match block) each time an entry gets added.
Addendum:
I simplified the original question too much and realized it after seeing Fyodor's answer.
So I would like to add the additional part:
how could this also be done for cases like these:
type T =
| A of int
| B of string
| C of SomeOtherType
For such enum type T as you specified, you can just use regular comparison:
let countOfType t (l: T list) =
l
|> List.filter (fun x -> x = t)
|> List.length
Usage:
> countOfType A [A; A; B; C; A]
3
> countOfType B [A; A; B; C; A]
1
Try List.choose: ('a -> 'b option) -> 'a list -> 'b list, it filters list based on 'a -> 'b option selector. If selectors evaluates to Some, then value will be included, if selector evaluates to None, then value will be skipped. If you worry about allocations caused by instantiation of Some, then you'll have to implement version that will use ValueOption
let onlyA lis =
lis |> List.choose (function
| (A _) as a -> Some a
| _ -> None)
let onlyB lis =
lis |> List.choose (function
| (B _) as b -> Some b
| _ -> None)
let lis = [
A 1
A 22
A 333
B ""
B "123"
]
lis |> onlyA |> List.length |> printfn "%d"
You can pattern match, and throw away the data, to create a function for the filter.
type T =
| A of int
| B of string
| C of float
[A 3;A 1;B "foo";B "bar";C 3.1; C 4.6]
|> List.filter (fun x ->
match x with
| A _ -> true
| B _ -> false
| C _ -> false
)
|> List.length
But in general i would asume, that you create a predicate function in your modul.
let isA x =
match x with
| A _ -> true
| _ -> false
if you have those functions you can just write
[A 3;A 1;B "foo";B "bar";C 3.1; C 4.6]
|> List.filter isA
|> List.length

F# : filtering None out and keeping only Some

A quick question on how to effectively group/filter list/seq.
Filter for only records where the optional field is not None
Remove the "option" parameter to make future processes easier (as None has been filtered out)
Group (this is of no problem I believe)
Am I using the best approach?
Thanks!
type tmp = {
A : string
B : int option }
type tmp2 = {
A : string
B : int }
let inline getOrElse (dft: 'a) (x: 'a option) =
match x with
| Some v -> v
| _ -> dft
let getGrouped (l: tmp list) =
l |> List.filter (fun a -> a.B.IsSome)
|> List.map (fun a -> {A = a.A ; B = (getOrElse 0 (a.B)) })
|> List.groupBy (fun a -> a.A)
The most natural approach for map+filter when option is involved is to use choose, which combines those two operations and drops the option wrapper from the filtered output.
Your example would look something like this:
let getGrouped (l: tmp list) =
l
|> List.choose (fun a ->
a.B
|> Option.map (fun b -> {A = a.A; B = b})
|> List.groupBy (fun a -> a.A)
The simple solution is just use the property that an option can be transformed to list with one or zero elements then you can define a function like:
let t1 ({A=a; B=b} : tmp) =
match b with
| (Some i) -> [{ A = a; B= i}]
| _ -> []
let getGrouped (l: tmp list) =
l |> List.collect t1
|> List.groupBy (fun a -> a.A)

Church Numerals in F#

I have been trying to implement church numerals in F#. They were briefly introduced in a course at college and I may have gone down the rabbit hole a bit since then. I have working Predecessor, Successor, Add and Operations but I can't get subtract to work. I'm trying to implement subtract b applying predecessor multiple times. What I find peculiar is that the penultimate line in my code works but what I assume is equivalent, the last line, does not work. There is a type mismatch.
I'm very new to F# so any help would be appreciated. Thank you.
//Operations on tuples
let fst (a,b) = a
let snd (a,b) = b
let pair a b = (a,b)
//Some church numerals
let c0 (f:('a -> 'a)) = id
let c1 (f:('a -> 'a)) = f
let c2 f = f << f
let c3 f = f << f << f
let c4 f = f << f << f << f
// Successor and predecessor
let cSucc (b,(cn:('a->'a)->('a->'a))) = if b then (b, fun f -> f << (cn f)) else (true, fun f -> (cn f))
let cPred (cn:('a->'a)->('a->'a)) = fun f -> snd (cn cSucc (false, c0)) f
//let cSucc2 cn = fun f -> f << (cn f)
// Add, Multiply and Subtract church numerals
let cAdd cn cm = fun f -> cn f << cm f
let cMult cn cm = cn >> cm
let cSub cn cm = cm cPred cn
//Basic function for checking validity of numeral operations
let f = (fun x -> x + 1)
//This works
(cPred << cPred) c3 f 0
//This doesn't
c2 cPred c3 f 0
This is the type mismatch error given (Intellisense says this is an error with cPred on the last line of the code). I can see the output type is inferred wrong. Is there a way to fix it or is there something fundamentally wrong with how I have written this implementation?
'((bool * (('a -> 'a) -> 'a -> 'a) -> bool * (('a -> 'a) -> 'a -> 'a)) -> bool * (('a -> 'a) -> 'a -> 'a) -> bool * (('a -> 'a) -> 'a -> 'a)) -> (bool * (('a -> 'a) -> 'a -> 'a) -> bool * (('a -> 'a) -> 'a -> 'a)) -> bool * (('a -> 'a) -> 'a -> 'a) -> bool * (('a -> 'a) -> 'a -> 'a)'
but given a
'((bool * (('a -> 'a) -> 'a -> 'a) -> bool * (('a -> 'a) -> 'a -> 'a)) -> bool * (('a -> 'a) -> 'a -> 'a) -> bool * (('a -> 'a) -> 'a -> 'a)) -> ('a -> 'a) -> 'a -> 'a'
The types ''a' and 'bool * (('a -> 'a) -> 'a -> 'a)' cannot be unified.
In the below explanation I will assume a definition of type CN<'a> = ('a -> 'a) -> 'a -> 'a (where "CN" stands for "Church Numeral") in order to shorten the explanation and reduce clutter.
Your attempted application of c2 to cPred fails, because c2 expects an argument of type 'a -> 'a, but cPred is not such function.
You may expect cPred to match the expected type, because you have declared it as CN<'a> -> CN<'a>, but that is not the true type. Because you are applying argument cn to type bool*CN<'a> -> bool*CN<'a> (which is the type of cSucc), the compiler infers that cn must have type of CN<bool*CN<'a>>, and therefore cPred gets the type of CN<bool*CN<'a>> -> CN<'a>, which does not match what c2 expects.
All of this comes down to this fact: functions lose their genericity when you pass them around as values.
Consider a simpler example:
let f (g: 'a -> 'a list) = g 1, g "a"
Such definition will not compile, because 'a is a parameter of f, not a parameter of g. Therefore, for a given execution of f, a specific 'a must be chosen, and it cannot be both int and string at the same time, and therefore, g cannot be applied to both 1 and "a".
Similarly, cn in cPred gets fixed to type bool*CN<'a> -> bool*CN<'a>, thus making the type of cPred itself incompatible with CN<_>.
In simple cases, there is an obvious workaround: pass g twice.
let f g1 g2 = g1 1, g2 "a"
let g x = [x]
f g g
// > it : int list * string list = [1], ["a"]
This way, g will lose genericity both times, but it will be specialized to different types - the first instance to int -> int list, the second - to string -> string list.
However, this is only a half-measure, suitable for the simplest cases only. A general solution will require the compiler to understand that we want 'a to be a parameter of g, not a parameter of f (this is usually referred to as "higher-rank type"). In Haskell (more specifically, GHC), there is a straightforward way to do this, with the RankNTypes extension enabled:
f (g :: forall a. a -> [a]) = (g 1, g "a")
g x = [x]
f g
==> ([1], ["a"])
Here, I explicitly tell the compiler that the parameter g has its own generic parameter a by including forall a in its type declaration.
F# does not have such explicit support for this, but it does offer a different feature that can be used to accomplish the same result - interfaces. Interfaces may have generic methods, and these methods do not lose genericity when interface instances are passed around. So we can reformulate the above simple example like this:
type G =
abstract apply : 'a -> 'a list
let f (g: G) = g.apply 1, g.apply "a"
let g = { new G with override this.apply x = [x] }
f g
// it : int list * string list = ([1], ["a"])
Yes, the syntax for declaring such "higher-rank functions" is heavy, but that's all F# has to offer.
So, applying this to your original problem, we need to declare CN as an interface:
type CN =
abstract ap : ('a -> 'a) -> 'a -> 'a
Then we can construct some numbers:
let c0 = { new CN with override __.ap f x = x }
let c1 = { new CN with override __.ap f x = f x }
let c2 = { new CN with override __.ap f x = f (f x) }
let c3 = { new CN with override __.ap f x = f (f (f x)) }
let c4 = { new CN with override __.ap f x = f (f (f (f x))) }
Then cSucc and cPred:
let cSucc (b,(cn:CN)) =
if b
then (b, { new CN with override __.ap f x = f (cn.ap f x) })
else (true, cn)
let cPred (cn:CN) = snd (cn.ap cSucc (false, c0))
Note that cPred now has inferred type of CN -> CN, exactly what we need.
Arithmetic functions:
let cAdd (cn: CN) (cm: CN) = { new CN with override __.ap f x = cn.ap f (cm.ap f x) }
let cMult (cn: CN) (cm: CN) = { new CN with override __.ap f x = cn.ap cm.ap f x }
let cSub (cn: CN) (cm: CN) = cm.ap cPred cn
Note, all of them get the inferred type of CN -> CN -> CN, as expected.
And finally, your examples:
let f = (fun x -> x + 1)
//This works
((cPred << cPred) c3).ap f 0
//This also works now
(c2.ap cPred c3).ap f 0

Church encoded Free monad in F#

I am trying to express the Church encoding of the Free monad in F#. Free is specialized to a particular functor, Effect.
I am able to write both return_ : 'T -> Free<'T> and bind: ('T -> Free<'U>) -> Free<'T> -> Free<'U> without any problems.
A sketch of my implementation is given below.
type Effect<'T>
= GetStr of (string -> 'T)
| PutStr of string * 'T
module Effect =
let map (f: 'a -> 'b) : Effect<'a> -> Effect<'b> = function
| GetStr k ->
GetStr(f << k)
| PutStr (s,t) ->
PutStr(s, f t)
type Free<'T> =
abstract Apply : ('T -> 'R) -> (Effect<'R> -> 'R) -> 'R
module Free =
let inline runFree (f:Free<'T>) (kp: 'T -> 'R) (kf: Effect<'R> -> 'R) : 'R =
f.Apply kp kf
let return_ (x: 'a) : Free<'a> =
{ new Free<'a>
with
member __.Apply kp _ =
kp x
}
let bind (f: 'a -> Free<'b>) (m: Free<'a>) : Free<'b> =
{ new Free<'b>
with
member __.Apply kp kf =
runFree m
(fun a ->
runFree (f a) kp kf
)
kf
}
When I try to write an interpreter for this encoding, I hit a problem.
Given the following code:
module Interpret =
let interpretEffect = function
| GetStr k ->
let s = System.Console.ReadLine()
(k s , String.length s)
| PutStr(s,t) ->
do System.Console.WriteLine s
(t , 0)
let rec interpret (f: Free<string * int>) =
Free.runFree
f
(fun (str,len) -> (str,len))
(fun (a: Effect<Free<string*int>>) ->
let (b,n) = interpretEffect a
let (c,n') = interpret b
(c, n + n')
)
I get a type error in the third argument to Free.runFree within the interpret function:
...
(fun (a: Effect<Free<string*int>>) ->
^^^^^^^^^^^^^^^^^^ ------ Expecting a Effect<string * int> but given a Effect<Free<string*int>>
I understand why this is happening (the result type of the first function determines 'R === string*int) and suspect that can be solved using a rank-2 function (which can be encoded in F# e.g. http://eiriktsarpalis.github.io/typeshape/#/33) but I am not sure how to apply it.
Any pointers would be much appreciated.
Michael
You do not need to do anything there, the compiler suggested type is in fact correct (and in line with the type of runFree).
It seems that what you're thinking of there is Scott encoding (ripped from this Haskell question):
runFree :: Functor f => (a -> r) -> (f (F f a) -> r) -> F f a -> r
where F f a would be your Effect-specialised Free<'a>, and f (F f a) would be Effect<Free<'a>>, which is what you're trying to use.
Whereas Church encoding would be:
runFree :: Functor f => (a -> r) -> (f r -> r) -> F f a -> r
where f r is Effect<'a> - thus making it easier to express in F# (which is why I assume you're using it in the first place.
This is what I had for interpret:
let rec interpret (f: Free<string * int>) =
Free.runFree
f
(fun (str,len) -> (str,len))
(fun (a: Effect<_>) ->
let (b,n) = interpretEffect a
let (c,n') = interpret (Free.pureF b)
(c, n + n')
)
where pureF is
let pureF (x: 'a) : Free<'a> =
{ new Free<'a> with member __.Apply kp _ = kp x }
i.e. your return_ function.
I think defining the corresponding freeF function would clear some things (like why is Effect<'a> a functor - you're not making use of this fact anywhere in the code you pasted).

Dynamic functions in F#

I'm trying to explore the dynamic capabilities of F# for situations where I can't express some function with the static type system. As such, I'm trying to create a mapN function for (say) Option types, but I'm having trouble creating a function with a dynamic number of arguments. I've tried:
let mapN<'output> (f : obj) args =
let rec mapN' (state:obj) (args' : (obj option) list) =
match args' with
| Some x :: xs -> mapN' ((state :?> obj -> obj) x) xs
| None _ :: _ -> None
| [] -> state :?> 'output option
mapN' f args
let toObjOption (x : #obj option) =
Option.map (fun x -> x :> obj) x
let a = Some 5
let b = Some "hi"
let c = Some true
let ans = mapN<string> (fun x y z -> sprintf "%i %s %A" x y z) [a |> toObjOption; b |> toObjOption; c |> toObjOption]
(which takes the function passed in and applies one argument at a time) which compiles, but then at runtime I get the following:
System.InvalidCastException: Unable to cast object of type 'ans#47' to type
'Microsoft.FSharp.Core.FSharpFunc`2[System.Object,System.Object]'.
I realize that it would be more idiomatic to either create a computation expression for options, or to define map2 through map5 or so, but I specifically want to explore the dynamic capabilities of F# to see whether something like this would be possible.
Is this just a concept that can't be done in F#, or is there an approach that I'm missing?
I think you would only be able to take that approach with reflection.
However, there are other ways to solve the overall problem without having to go dynamic or use the other static options you mentioned. You can get a lot of the same convenience using Option.apply, which you need to define yourself (or take from a library). This code is stolen and adapted from F# for fun and profit:
module Option =
let apply fOpt xOpt =
match fOpt,xOpt with
| Some f, Some x -> Some (f x)
| _ -> None
let resultOption =
let (<*>) = Option.apply
Some (fun x y z -> sprintf "%i %s %A" x y z)
<*> Some 5
<*> Some "hi"
<*> Some true
To explain why your approach does not work, the problem is that you cannot cast a function of type int -> int (represented as FSharpFunc<int, int>) to a value of type obj -> obj (represented as FSharpFunc<obj, obj>). The types are the same generic types, but the cast fails because the generic parameters are different.
If you insert a lot of boxing and unboxing, then your function actually works, but this is probably not something you want to write:
let ans = mapN<string> (fun (x:obj) -> box (fun (y:obj) -> box (fun (z:obj) ->
box (Some(sprintf "%i %s %A" (unbox x) (unbox y) (unbox z))))))
[a |> toObjOption; b |> toObjOption; c |> toObjOption]
If you wanted to explore more options possible thanks to dynamic hacks - then you can probably do more using F# reflection. I would not typically use this in production (simple is better - I'd just define multiple map functions by hand or something like that), but the following runs:
let rec mapN<'R> f args =
match args with
| [] -> unbox<'R> f
| x::xs ->
let m = f.GetType().GetMethods() |> Seq.find (fun m ->
m.Name = "Invoke" && m.GetParameters().Length = 1)
mapN<'R> (m.Invoke(f, [| x |])) xs
mapN<obj> (fun a b c -> sprintf "%d %s %A" a b c) [box 1; box "hi"; box true]

Resources