Generic values in F# modules? - f#

Consider a generic container like:
type Foo<'t> =
{
Foo : 't
}
This generic function works OK:
module Foo =
let inline emptyFoo () =
{
Foo = LanguagePrimitives.GenericZero
}
But this value does not:
module Foo =
let emptyFoo =
{
Foo = LanguagePrimitives.GenericZero
}
This is because the compiler infers emptyFoo to have type Foo<obj>.
However, the standard library has generic values like List.empty, so how is that achieved there?

You have to make it explicitly generic.
List.empty is implemented like this:
let empty<'T> = ([ ] : 'T list)

You could implement a List by yourself, with an empty. It looks like this.
type L<'a> =
| Null
| Cons of 'a * L<'a>
module L =
let empty = Null
let xs = Cons(1, Cons(2, L.empty))
let ys = Cons(1.0,Cons(2.0,L.empty))
So, why does L.empty in this case works in a generic way? Because the value Null has no special value attached to it. You could say, it is compatible with every other generic.
In your Record on the other hand, you always must produce a value. LanguagePrimitive.GenericZero is not some Generic value. It help so to resolve to a special zero value, and this value is determined by the other code you write.
For example
let x = LanguagePrimitives.GenericZero
is also obj
let x = LanguagePrimitives.GenericZero + 1
will be int. And
let x = LanguagePrimitives.GenericZero + 1.0
will be float. So in some case you can think of GenericZero just as a placeholder for zero for the special type you need, but the code needs to determine at this point, which type you want.
You could change your type, with an option to provide a real empty.
type Foo<'t> = {
Foo: 't option
}
module Foo =
let empty = { Foo = None }
let x = Foo.empty // Foo<'a>
let y = { x with Foo = Some 1 } // Foo<int>
let z = { x with Foo = Some 1.0 } // Foo<float>
Zero Member
Maybe you want a Zero Member on some types. For example
type Vector3 = {X:float; Y:float; Z:float} with
static member create x y z = {X=x; Y=y; Z=z}
static member (+) (a,b) = Vector3.create (a.X + b.X) (a.Y + b.Y) (a.Z + b.Z)
static member Zero = Vector3.create 0.0 0.0 0.0
static member DivideByInt(a,b) =
Vector3.create
(LanguagePrimitives.DivideByInt a.X b)
(LanguagePrimitives.DivideByInt a.Y b)
(LanguagePrimitives.DivideByInt a.Z b)
then you can write
let xs = [1;2;3]
let ys = [Vector3.create 1.0 1.0 1.0; Vector3.create 1.0 1.0 1.0]
let inline sum xs =
List.fold (fun a b -> a + b) LanguagePrimitives.GenericZero xs
let sumx = sum xs // int: 6
let sumy = sum ys // Vector3: 2.0 2.0 2.0

Related

Implementing let! ... and! ... in a custom Computation Expression

I want to add support to my Computation Expression builder for this construct:
let f =
foo {
let! x =
foo {
return 1
}
and! y =
foo {
return 2
}
return x + y
}
The compiler says I must implement either Bind2 or MergeSource. However, I cannot find them in the docs.
What signatures should these have? Can you give a simple example?
Here's a simple builder that works with your example:
type Foo<'t> = MkFoo of 't
type FooBuilder() =
member _.Bind(MkFoo x, f) = f x
member _.Return(x) = MkFoo x
member _.MergeSources(MkFoo x, MkFoo y) = MkFoo (x, y)
let foo = FooBuilder()
let f =
foo {
let! x = foo { return 1 }
and! y = foo { return 2 }
return x + y
}
printfn "%A" f // output: MkFoo 3
The purpose of MergeSources is to create a tuple of results that will be automatically de-tupled by the compiler. You might also find this example and this SO question useful.

How to make a lazy computational workflow?

I'm trying to write a computational workflow which would allow a computation which can produce side effects like log or sleep and a return value
A usage example would be something like this
let add x y =
compute {
do! log (sprintf "add: x = %d, y= %d" x y)
do! sleep 1000
let r = x + y
do! log (sprintf "add: result= %d" r)
return r
}
...
let result = run (add 100 1000)
and I would like the side effects to be produced when executeComputation is called.
My attempt is
type Effect =
| Log of string
| Sleep of int
type Computation<'t> = Computation of Lazy<'t * Effect list>
let private bind (u : 'u, effs : Effect list)
(f : 'u -> 'v * Effect list)
: ('v * Effect list) =
let v, newEffs = f u
let allEffects = List.append effs newEffs
v, allEffects
type ComputeBuilder() =
member this.Zero() = lazy ((), [])
member this.Return(x) = x, []
member this.ReturnFrom(Computation f) = f.Force()
member this.Bind(x, f) = bind x f
member this.Delay(funcToDelay) = funcToDelay
member this.Run(funcToRun) = Computation (lazy funcToRun())
let compute = new ComputeBuilder()
let log msg = (), [Log msg]
let sleep ms = (), [Sleep ms]
let run (Computation x) = x.Force()
...but the compiler complains about the let! lines in the following code:
let x =
compute {
let! a = add 10 20
let! b = add 11 2000
return a + b
}
Error FS0001: This expression was expected to have type
'a * Effect list
but here has type
Computation<'b> (FS0001)
Any suggestions?
The main thing that is not right with your definition is that some of the members of the computation builder use your Computation<'T> type and some of the other members use directly a pair of value and list of effects.
To make it type check, you need to be consistent. The following version uses Computation<'T> everywhere - have a look at the type signature of Bind, for example:
let private bind (Computation c) f : Computation<_> =
Computation(Lazy.Create(fun () ->
let u, effs = c.Value
let (Computation(c2)) = f u
let v, newEffs = c2.Value
let allEffects = List.append effs newEffs
v, allEffects))
type ComputeBuilder() =
member this.Zero() = Computation(lazy ((), []))
member this.Return(x) = Computation(lazy (x, []))
member this.ReturnFrom(c) = c
member this.Bind(x, f) = bind x f
member this.Delay(funcToDelay:_ -> Computation<_>) =
Computation(Lazy.Create(fun () ->
let (Computation(r)) = funcToDelay()
r.Value))

How to write code in F# for what functors do in OCaml?

I have many programs written in OCaml, some of them use functors. Now, I am considering of writing and re-writing a part of code in F# (to benefit some advantages that OCaml does not have). One thing I am afraid of is to write code in F# for what functors do in OCaml.
For instance, how could we emulate this example from OCaml manual in F#?
type comparison = Less | Equal | Greater
module type ORDERED_TYPE = sig
type t
val compare: t -> t -> comparison
end
module Set =
functor (Elt: ORDERED_TYPE) -> struct
type element = Elt.t
type set = element list
let empty = []
let rec add x s =
match s with
[] -> [x]
| hd::tl ->
match Elt.compare x hd with
Equal -> s (* x is already in s *)
| Less -> x :: s (* x is smaller than all elements of s *)
| Greater -> hd :: add x tl
end
module OrderedString = struct
type t = string
let compare x y = if x = y then Equal else if x < y then Less else Greater
end
module OrderedInt = struct
type t = int
let compare x y = if x = y then Equal else if x < y then Less else Greater
end
module StringSet = Set(OrderedString)
module IntSet = Set(OrderedInt)
let try1 () = StringSet.add "foo" StringSet.empty
let try2 () = IntSet.add 2 IntSet.empty
Here is a bit different approach that achieves same outcome using a generic class and one object per type.
type Comparison = Less | Equal | Greater
type Set<'a>(compare : 'a -> 'a -> Comparison) =
member this.Empty : 'a list = []
member this.Add x s =
match s with
| [] -> [x]
| hd::tl ->
match compare x hd with
| Equal -> s (* x is already in s *)
| Less -> x :: s (* x is smaller than all elements of s *)
| Greater -> hd :: this.Add x tl
let compare x y = if x = y then Equal else if x < y then Less else Greater
let compareFloats (x : float) (y : float) = if x = y then Equal else if x < y then Less else Greater
// Note that same generic compare function can be used for stringSet and intSet
// as long as the type parameter is explicitly given
let stringSet = Set<string>(compare)
let intSet = Set<int>(compare)
// Type parameter not needed, because compareFloats is not generic
let floatSet = Set(compareFloats)
let try1 () = stringSet.Add "foo" stringSet.Empty // -> ["foo"]
let try2 () = intSet.Add 2 intSet.Empty // -> [2]
let try3 () = floatSet.Add 3.0 floatSet.Empty // -> [3.0]
As you noticed, F# doesn't have functors - F# modules cannot be parameterized by types. You can get similar results in F# using the object oriented parts of the language - interfaces, generic classes and inheritance.
Here's a heavy handed approach at emulating your example.
type Comparison = Less | Equal | Greater
/// Interface corresponding to ORDERED_TYPE signature
type IOrderedType<'a> =
abstract Value: 'a
abstract Compare: IOrderedType<'a> -> Comparison
/// Type that implements ORDERED_TYPE signature, different instantiations
/// of this type correspond to your OrderedInt/OrderedString modules.
/// The 't: comparison constraint comes from the fact that (<) operator
/// is used in the body of Compare.
type Ordered<'t when 't: comparison> (t: 't) =
interface IOrderedType<'t> with
member this.Value = t
member this.Compare (other: IOrderedType<'t>) =
if t = other.Value then Equal else if t < other.Value then Less else Greater
/// A generic type that works over instances of IOrderedType interface.
type Set<'t, 'ot when 't: comparison and 'ot :> IOrderedType<'t>> (coll: IOrderedType<'t> list) =
member this.Values =
coll |> List.map (fun x -> x.Value)
member this.Add(x: 't) =
let rec add (x: IOrderedType<'t>) s =
match coll with
| [] -> [x]
| hd::tl ->
match x.Compare(hd) with
| Equal -> s (* x is already in s *)
| Less -> x :: s (* x is smaller than all elements of s *)
| Greater -> hd :: add x tl
Set<'t, 'ot>(add (Ordered(x)) coll)
static member Empty = Set<'t, 'ot>(List.empty)
/// A helper function for Set.Add. Useful in pipelines.
module Set =
let add x (s: Set<_,_>) =
s.Add(x)
/// Type aliases for different instantiations of Set
/// (these could have easily been subtypes of Set as well)
type StringSet = Set<string, Ordered<string>>
type IntSet = Set<int, Ordered<int>>
let try1 () = Set.add "foo" StringSet.Empty
let try2 () = Set.add 2 IntSet.Empty
try1().Values
try2().Values
The functional way in F# would rely mostly on type inference avoiding OOP structures like interface or types with member.
type Comparison = Less | Equal | Greater
type OrderedSet<'t> = 't list // type alias, not really necessary
module OrderedSet =
let empty : OrderedSet<_> = List.empty // just an empty list
let values (s : OrderedSet<_>) : OrderedSet<_> = s // identity function
let add compare x (s : OrderedSet<_>) : OrderedSet<_> =
let rec addR s =
match s with
| [] -> [x]
| hd::tl ->
match compare x hd with
| Equal -> s (* x is already in s *)
| Less -> x :: s (* x is smaller than all elements of s *)
| Greater -> hd :: addR tl
addR s
let compare x y = if x = y then Equal else if x < y then Less else Greater
let compareFloats (x : float) y = if x = y then Equal else if x < y then Less else Greater
let addGeneric v = add compare v
let addFloat v = add compareFloats v
And it is used like this:
let try1 () = OrderedSet.addGeneric "foo" OrderedSet.empty |> OrderedSet.addGeneric "bar"
let try2 () = OrderedSet.addGeneric 2 OrderedSet.empty |> OrderedSet.addGeneric 3
let try3 () = OrderedSet.empty
|> OrderedSet.addFloat 3.0
|> OrderedSet.addFloat 1.0
|> OrderedSet.addFloat 2.0
try1() |> printfn "%A" // OrderedSet<string> = ["bar"; "foo"]
try2() |> printfn "%A" // OrderedSet<int> = [2; 3]
try3() |> printfn "%A" // OrderedSet<float> = [1.0; 2.0; 3.0]
The type alias type OrderedSet<'t> = 't list and the functions empty and values are not really necessary but they help to mask the actual implementation (in case that is desirable).

overload dereference (!) and assignment (:=) operators in f#

I'm trying to overload the dereference (!) and assignment (:=) operators but not globally. I still want to keep the usual ref op overloads. Here's some code to illustrate the issues:
type MyVar<'a>(init:'a) =
let mutable _value = init
member __.Get() = _value
member __.Set x = _value <- x
//static member (!) (s:MyVar<'a>) = s.Get() // compiles, doesn't work
//static member (:=) (d:MyVar<'a>, s) = d.Set(s) // warning, doesn't work
//let inline (!) (x :MyVar<'a>) = x.Get() // overrides !ref
//let inline (:=) (x :MyVar<'a>) (v :'a) = x.Set(v) // overrides ref := v
let inline (!!) (x :MyVar<'a>) = x.Get() // works but ugly
let inline (.=) (x :MyVar<'a>) (v :'a) = x.Set(v) // works ... meh
let test_myvar() =
let mv = new MyVar<_>("wee")
let r = ref 100
let x = !mv
let y = !!mv
let z = !r
mv .= "haaa"
r := 42
Solution:
#Carsten's solution is what I was looking for & works. However, it turns out that I am using Websharper which compiles using Quotations and #Carstens solution becomes a little more complex. Since Websharper.UI.Next includes that solution, all I had to was include in my project, and it works!
you can get this to work with static constraints - by overloading the (!) and (:=) operators as you tried:
type MyVar<'a>(init:'a) =
let mutable _value = init
member __.Value with get () = _value and set v = _value <- v
let inline (!) a =
(^a : (member Value : ^b) a)
let inline (:=) a v =
(^a : (member Value : ^b with set) (a, v))
I removed your accessors because I only need the same as Ref<'a> has (but you can re-add them)
Demonstration
Here is an F#-interactive session demonstrating this with your values:
val mv : MyVar<string>
val r : int ref = {contents = 100;}
> !mv;;
val it : string = "wee"
> !r;;
val it : int = 100
> mv := "It works";;
val it : unit = ()
> !mv;;
val it : string = "It works"
> r := 50;;
val it : unit = ()
> !r;;
val it : int = 50
remark
I'm not sure if I would really do this though - you only reinvent the Ref-cell (as an class) and gain nothing and of course it might be hard to read for others - so treat with care.

Alternative approach to avoid "Incomplete pattern match" warning

I have written a function that takes an array as input and returns an array of equal size as output. For example:
myFunc [| "apple"; "orange"; "banana" |]
> val it : (string * string) [] =
[|("red", "sphere"); ("orange", "sphere"); ("yellow", "oblong")|]
Now I want to assign the results via a let binding. For example:
let [|
( appleColor, appleShape );
( orangeColor, orangeShape );
( bananaColor, bananaShape )
|] =
myFunc [| "apple"; "orange"; "banana" |]
Which works great...
> val orangeShape : string = "sphere"
> val orangeColor : string = "orange"
> val bananaShape : string = "oblong"
> val bananaColor : string = "yellow"
> val appleShape : string = "sphere"
> val appleColor : string = "red"
...except it produces a warning:
warning FS0025: Incomplete pattern matches on this expression. For example, the value '[|_; _; _; _|]' may indicate a case not covered by the pattern(s).
The source and reason for the warning has already been covered, I'm just looking for a succinct work-around. This function call occurs near the top of my function, and I don't like the idea of putting the entire function body inside a match:
let otherFunc =
match myFunc [| "apple"; "orange"; "banana" |] with
| [|
( appleColor, appleShape );
( orangeColor, orangeShape );
( bananaColor, bananaShape )
|] ->
// ... the rest of my function logic
| _ -> failwith "Something impossible just happened!"
That just smells bad. I don't like the idea of ignoring the warning either - goes against my better judgment. Are there any other options open to me, or do I just need to find a different approach entirely?
One possibility if you expect this kind of calling pattern to be frequent is to make wrappers that act on the sizes of tuples you expect, e.g.
myFunc3 (in1,in2,in3) =
match myFunc [|in1;in2;in3|] with
[|out1;out2;out3|] -> out1, out2, out3
_ -> failwith "Internal error"
etc. But all it does is move the ugly code to a standard place, and writing out the wrappers will be inconvenient.
I don't think there's any better option with this API, because there's no way to tell the compiler that myFunc always returns the same number of elements it is passed.
Another option might be to replace myFunc with an IDisposable class:
type MyClass() =
let expensiveResource = ...
member this.MyFunc(v) = ...calculate something with v using expensiveResource
interface IDisposable with
override this.Dispose() = // cleanup resource
and then use it in a block like
use myClass = new MyClass()
let appleColor, appleShape = myClass.MyFunc(apple)
...
Adapting #Ganesh's answer, here's a primitive way to approach the problem:
let Tuple2Map f (u, v)
= (f u, f v)
let Tuple3Map f (u, v, w)
= (f u, f v, f w)
let Tuple4Map f (u, v, w, x)
= (f u, f v, f w, f x)
Example:
let Square x = x * x
let (a,b) = Tuple2Map Square (4,6)
// Output:
// val b : int = 36
// val a : int = 16
But I guess something even more primitive would be this:
let Square x = x * x
let (a,b) = (Square 4, Square 6)
And if the function name is too long, e.g.
// Really wordy way to assign to (a,b)
let FunctionWithLotsOfInput w x y z = w * x * y * z
let (a,b) =
(FunctionWithLotsOfInput input1 input2 input3 input4A,
FunctionWithLotsOfInput input1 input2 input3 input4B)
We can define temporary function
let FunctionWithLotsOfInput w x y z = w * x * y * z
// Partially applied function, temporary function
let (a,b) =
let f = (FunctionWithLotsOfInput input1 input2 input3)
(f input4A, f input4B)

Resources