The msdn page documenting Records (F#) details record expressions for record construction and record patterns for deconstruction, the latter without naming them as such.
Here's an example which uses both techniques for an arithmetic operator:
// Simple two-dimensional generic vector defintion
type 'a UV =
{ U : 'a; V : 'a }
static member inline (+) ({ U = au; V = av }, { U = bu; V = bv }) =
{ U = au + bu; V = av + bv }
This appears unwieldy and not very readable. For deconstruction, there are dot-notation or functions as alternatives. Since the dot-notation operator has a special dispensation in section 8.4.2 Name Resolution and Record Field Labels of the spec (an expression’s type may be inferred from a record label), there's normally no need to annotate. Accessor functions like let u { U = u } = u wouldn't give us any advantages then.
For construction, I think a case can be made for a function as record constructor. Access to the original constructor might even be restricted:
type 'a UV =
internal { U : 'a; V : 'a }
let uv u v = { U = u; V = v }
type 'a UV with
static member inline (+) (a, b) =
uv (a.U + b.U) (a.V + b.V)
Is this an idiomatic thing to do? How to package such functions in modules and handle namespace issues?
Short answer: I don't think there is a general convention here at the moment so it will be a personal decision in the end.
To summarise what you get for free with records in F# is:
Construct: { U = u; V = v } (bracket-notation)
Deconstruct: let u = record.u (dot-notation) and let {U = u} = record (pattern matching)
Update: {record with U = u} (bracket-notation)
But you don't get first class functions for free, if you want you can code them by hand.
The following is what I would personally use as convention:
A static member New with curried arguments for record construction.
For update and deconstruction I would use some kind of Lenses abstraction.
Here's an example of the code I would have to add by hand:
// Somewhere as a top level definition or in a base library
type Lens<'T,'U> = {Get: 'T -> 'U; Set: 'U -> 'T -> 'T } with
member l.Update f a = l.Set (f (l.Get a)) a
type UV<'a> = {U : 'a; V : 'a } with
// add these static members to your records
static member New u v : UV<'a> = {U = u; V = v}
static member u = {Get = (fun (x: UV<'a>) -> x.U); Set = fun t x -> {x with U = t}}
static member v = {Get = (fun (x: UV<'a>) -> x.V); Set = fun t x -> {x with V = t}}
let uvRecord = UV.New 10 20
let u = UV.u.Get uvRecord
let uvRecord1 = UV.u.Set (u+1) uvRecord
let uvRecord2 = UV.u.Update ((+)1) uvRecord
This way I would have first class functions for construction, deconstruction but also for updates plus other very interesting Lenses properties as you can read in this post.
UPDATE (in response to your comments)
Of course they can be defined later, what does it change?
The same applies for the New constructor, it can be defined later but that's actually a good thing.
The accessor functions you defined can also be defined later, indeed any first-class getter, setter or updater value can be defined later.
Anyway the answer to your question is "no, there are no conventions" the rest it's a personal decision, which would be my decision and also many Haskellers are pushing to get some kind of automatic Lenses for Haskell records.
Why would I decide to go this way? Because in terms of lines of code the effort of adding a simple accessor function is almost the same as adding a get-Lens, so for the same price I get more functionality.
If you are not happy with the Lenses discussion please tell me, I can delete it and leave the short answer, or I can delete the whole answer too if it's confusing instead of clarifying.
Or may be I misunderstood your question, for me your question was about which convention is generally used to add first-class constructors, getters and setters values for records.
Composition is not the only advantage of Lenses, you can do many things, keep reading about them, they provide a very interesting abstraction and not only restricted to records.
Related
F# does not (currently) support type-classes. However, F# does support the OOP aspects of C#.
I was wondering, what is lost doing this approach compared to true type-classes?
// A concrete type
type Foo =
{
Foo : int
}
// "Trait" for things that can be shown
type IShowable =
abstract member Show : unit -> string
module Showable =
let show (showable : IShowable) =
showable.Show()
// "Witness" of IShowable for Foo
module Foo =
let asShowable (foo : Foo) =
{
new IShowable with
member this.Show() = string foo.Foo
}
// Slightly awkward usage
{ Foo = 123 }
|> Foo.asShowable
|> Showable.show
|> printfn "%s"
Your suggestion works for simple typeclasses that operate on a single value of a type, like Show. However, what happens when you need a typeclass that isn't so object-oriented? For example, when we want to add two numbers, neither one corresponds to OO's this object:
// not real F#
typeclass Numeric<'a> = // e.g. Numeric<int> or Numeric<float>
abstract member (+) : 'a -> 'a -> 'a // e.g. 2 + 3 = 5 or 2.0 + 3.0 = 5.0
...
Also, keep in mind that many useful typeclasses require higher-kinded types. For example, consider the monad typeclass, which would look something like this:
// not real F#
typeclass Monad<'m<_>> = // e.g. Monad<Option<_>> or Monad<Async<_>>
abstract member Return<'a> : 'a -> 'm<'a>
abstract member Bind<'a, 'b> : 'm<'a> -> ('a -> 'm<'b>) -> 'm<'b>
There's no good way to do this with .NET interfaces.
Higher-kinded type classes are indeed impossible to model with interfaces, but that's just because F# does not support higher-kindedness, not because of type classes themselves.
The deeper thing to note is that your encoding isn't actually correct. Sure, if you just need to call show directly, you can do asShowable like that, but that's just the simplest case. Imagine you needed to pass the value to another function that wanted to show it later? And then imagine it was a list of values, not a single one:
let needsToShow (showable: IShowable) (xs: 'a list) =
xs |> List.iter (fun x -> ??? how do I show `x` ???)
No, this wouldn't do of course. The key is that Show should be a function 'a -> string, not unit -> string. And this means that IShowable itself should be generic:
// Haskell: class Showable a where show :: a -> String
type IShowable<'a> with
abstract member Show : 'a -> string
// Haskell: instance Showable Foo where show (Foo i) = show i
module Foo =
let showable = { new IShowable<Foo> with member _.Show foo = string foo.Foo }
// Haskell: needsToShow :: Show a => [a] -> IO ()
let needsToShow (showable: IShowable<'a>) (xs: 'a list) =
xs |> List.iter (fun x -> printfn "%s" (showable.Show x))
// Haskell: needsToShow [Foo 1, Foo 42]
needsToShow Foo.showable [ { Foo: 1 }; { Foo: 42 } ]
And this is, essentially, what type classes are: they're indeed merely dictionaries of functions that are passed everywhere as extra parameters. Every type has such dictionary either available right away (like Foo above) or constructable from other such dictionaries, e.g.:
type Bar<'a> = Bar of 'a
// Haskell: instance Show a => Show (Bar a) where show (Bar a) = "Bar: " <> show a
module Bar =
let showable (showA: IShowable<'a>) =
{ new IShowable<Bar<'a>> with member _.Show (Bar a) = "Bar: " + showA.Show a }
This is completely equivalent to type classes. And in fact, this is exactly how they're implemented in languages like Haskell or PureScript in the first place: like dictionaries of functions being passed as extra parameters. It's not a coincidence that constraints on function type signatures even kinda look like parameters - just with a fat arrow instead of a thin one.
The only real difference is that in F# you have to do that yourself, while in Haskell the compiler figures out all the instances and passes them for you.
And this difference turns out to be kind of important in practice. I mean, sure, for such a simple example as Show for the immediate parameter, you can just pass the damn instance yourself. And even if it's more complicated, I guess you could suck it up and pass a dozen extra parameters.
But where this gets really inconvenient is operators. Operators are functions too, but with operators there is nowhere to stick an extra parameter (or dozen). Check this out:
x = getY >>= \y -> getZ y <&> \z -> y + 42 > z
Here I used four operators from four different classes:
>>= comes from Monad
<&> from Functor
+ from Num
> from Ord
An equivalent in F# with passing instances manually might look something like:
let x =
bind Foo.monad getY <| fun y ->
map Bar.functor (getZ y) <| fun z ->
gt Int.ord (add Int.num y 42) z
Having to do that everywhere is quite unreasonable, you have to agree.
And this is why many F# operators either use SRTPs (e.g. +) or rely on "known" interfaces (e.g. <) - all so you don't have to pass instances manually.
For a while F# has supported the ability to auto-quote using [<ReflectedDefinitionAttribute>]. Is there anything similar for laziness?
e.g.
member __.Quoted ([<ReflectedDefinitionAttribute>] quotation:Expr<'T>) = ...
member __.Thunked ([<LazyAttribute>] thunk:Lazy<'T>) = ...
I suppose I could use something like
member __.Quoted ([<ReflectedDefinitionAttribute>] quotation:Expr<'T>) =
Lazy (evaluate (<# fun () -> %quotation #>)) // evaluate using Unquote or similar
But wouldn't this be costly?
UPDATE:
I found a hack, it's not exactly what I would like but it give the correct behavior.
type Signal = Signal with
member __.Return x = x
member __.Delay (f:unit -> _) = f
let a = Signal { return randint }
let b = Signal { return randint }
let c = Signal { return a() + b() }
There is nothing like the ReflectedDefinition attribute for automatically turning things into delayed Lazy<'T> computations.
You are right that automatically quoting the argument achieves something like this. You could use the (very limited) LeafExpressionConverter.EvaluateQuotation to do this for some limited kinds of expressions, but as you note, this would be inefficient. The following is a proof of concept though (but you cannot call custom functions in the branches as this uses LINQ expressions):
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Linq.RuntimeHelpers
type A =
static member If<'T>(c:bool,
[<ReflectedDefinition>] t:Expr<'T>,
[<ReflectedDefinition>] f:Expr<'T>) =
if c then LeafExpressionConverter.EvaluateQuotation t :?> 'T
else LeafExpressionConverter.EvaluateQuotation f :?> 'T
A.If(1 = 2, 0, 1)
In practice, I think a more reasonable approach is to just use the built-in Lazy<'T> values. F# has a (not widely known) lazy keyword that gives you a bit nicer syntax for creating those:
let iff c (t:Lazy<_>) (f:Lazy<_>) =
if c then t.Value else f.Value
iff (1 = 2)
(lazy (printfn "true"; 41))
(lazy (printfn "false"; 42))
I'm trying to wrap my head around mon-, err, workflows in F# and while I think that I have a pretty solid understanding of the basic "Maybe" workflow, trying to implement a state workflow to generate random numbers has really got me stumped.
My non-completed attempt can be seen here:
let randomInt state =
let random = System.Random(state)
// Generate random number and a new state as well
random.Next(0,1000), random.Next()
type RandomWF (initState) =
member this.Bind(rnd,rest) =
let value, newState = rnd initState
// How to feed "newState" into "rest"??
value |> rest
member this.Return a = a // Should I maybe feed "initState" into the computation here?
RandomWF(0) {
let! a = randomInt
let! b = randomInt
let! c = randomInt
return [a; b; c]
} |> printfn "%A"
Edit: Actually got it to work! Not exactly sure how it works though, so if anyone wants to lay it out in a good answer, it's still up for grabs. Here's my working code:
type RandomWF (initState) =
member this.Bind(rnd,rest) =
fun state ->
let value, nextState = rnd state
rest value nextState
member this.Return a = fun _ -> a
member this.Run x = x initState
There are two things that make it harder to see what your workflow is doing:
You're using a function type for the type of your monad,
Your workflow not only builds up the computation, it also runs it.
I think it's clearer to follow once you see how it would look without those two impediments. Here's the workflow defined using a DU wrapper type:
type Random<'a> =
Comp of (int -> 'a * int)
let run init (Comp f) = f init
type Random<'a> with
member this.Run(state) = fst <| run state this
type RandomBuilder() =
member this.Bind(Comp m, f: 'a -> Random<_>) =
Comp <| fun state ->
let value, nextState = m state
let comp = f value
run nextState comp
member this.Return(a) = Comp (fun s -> a, s)
let random = RandomBuilder()
And here is how you use it:
let randomInt =
Comp <| fun state ->
let rnd = System.Random(state)
rnd.Next(0,1000), rnd.Next()
let rand =
random {
let! a = randomInt
let! b = randomInt
let! c = randomInt
return [a; b; c ]
}
rand.Run(0)
|> printfn "%A"
In this version you separately build up the computation (and store it inside the Random type), and then you run it passing in the initial state. Look at how types on the builder methods are inferred and compare them to what MSDN documentation describes.
Edit: Constructing a builder object once and using the binding as an alias of sorts is mostly convention, but it's well justified in that it makes sense for the builders to be stateless. I can see why having parameterized builders seems like a useful feature, but I can't honestly imagine a convincing use case for it.
The key selling point of monads is the separation of definition and execution of a computation.
In your case - what you want to be able to do is to take a representation of your computation and be able to run it with some state - perhaps 0, perhaps 42. You don't need to know the initial state to define a computation that will use it. By passing in the state to the builder, you end up blurring the line between definition and execution, and this simply makes the workflow less useful.
Compare that with async workflow - when you write an async block, you don't make the code run asynchronously. You only create an Async<'a> object representing a computation that will produce an object of 'a when you run it - but how you do it, is up to you. The builder doesn't need to know.
What's the most idiomatic way in F# to deal with the following. Suppose I have a property I want a type to satisfy that doesn't make sense on an instance level, but ideally I would like to have some pattern matching available against it?
To make this more concrete, I have defined an interface representing the concept of a ring (in the abstract algebra sense). Would I go for:
1.
// Misses a few required operations for now
type IRing1<'a when 'a: equality> =
abstract member Zero: 'a with get
abstract member Addition: ('a*'a -> 'a) with get
and let's assume I'm using it like this:
type Integer =
| Int of System.Numerics.BigInteger
static member Zero with get() = Int 0I
static member (+) (Int a, Int b) = Int (a+b)
static member AsRing
with get() =
{ new IRing1<_> with
member __.Zero = Integer.Zero
member __.Addition = Integer.(+) }
which allows me to write things like:
let ring = Integer.AsRing
which then lets me to nicely use the unit tests I've written for verifying the properties of a ring. However, I can't pattern match on this.
2.
type IRing2<'a when 'a: equality> =
abstract member Zero: 'a with get
abstract member Addition: ('a*'a -> 'a) with get
type Integer =
| Int of System.Numerics.BigInteger
static member Zero with get() = Int 0I
static member (+) (Int a, Int b) = Int (a+b)
interface IRing2<Integer> with
member __.Zero = Integer.Zero
member __.Addition with get() = Integer.(+)
which now I can pattern match, but it also means that I can write nonsense such as
let ring = (Int 3) :> IRing2<_>
3.
I could use an additional level of indirection and basically define
type IConvertibleToRing<'a when 'a: equality>
abstract member UnderlyingTypeAsRing : IRing3<'a> with get
and then basically construct the IRing3<_> in the same way as under #1.
This would let me write:
let ring = ((Int 3) :> IConvertibleToRing).UnderlyingTypeAsRing
which is verbose but at least what I'm writing doesn't read as nonsense anymore. However, next to the verbosity, the additional level of complexity gained doesn't really "feel" justifiable here.
4.
I haven't fully thought this one through yet, but I could just have an Integer type without implementing any interfaces and then a module named Integer, having let bound values for the Ring interfaces. I suppose I could then use reflection in a helper function that creates any IRing implementation for any type where there is also a module with the same name (but with a module suffix in it's compiled name) available? This would combine the benefits of #1 and #2 I guess, but I'm not sure whether it's possible and/or too contrived?
Just for background: Just for the heck of it, I'm trying to implement my own mini Computer Algebra System (like e.g. Mathematica or Maple) in F# and I figured that I would come across enough algebraic structures to start introducing interfaces such as IRing for unit testing as well as (potentially) later for dealing with general operations on such algebraic structures.
I realize part of what is or isn't possible here has more to do with restrictions on how things can be done in .NET rather than F#. If my intention is clear enough, I'd be curious to here in comments how other functional languages work around this kind of design questions.
Regarding your question about how can you implement Rings in other functional languages, in Haskell you will typically define a Type Class Ring with all Ring operations.
In F# there are no Type Classes, however you can get closer using inline and overloading:
module Ring =
type Zero = Zero with
static member ($) (Zero, a:int) = 0
static member ($) (Zero, a:bigint) = 0I
// more overloads
type Add = Add with
static member ($) (Add, a:int ) = fun (b:int ) -> a + b
static member ($) (Add, a:bigint) = fun (b:bigint) -> a + b
// more overloads
type Multiply = Multiply with
static member ($) (Multiply, a:int ) = fun (b:int ) -> a * b
static member ($) (Multiply, a:bigint) = fun (b:bigint) -> a * b
// more overloads
let inline zero() :'t = Zero $ Unchecked.defaultof<'t>
let inline (<+>) (a:'t) (b:'t) :'t= (Add $ a) b
let inline (<*>) (a:'t) (b:'t) :'t= (Multiply $ a) b
// Usage
open Ring
let z : int = zero()
let z': bigint = zero()
let s = 1 <+> 2
let s' = 1I <+> 2I
let m = 2 <*> 3
let m' = 2I <*> 3I
type MyCustomNumber = CN of int with
static member ($) (Ring.Zero, a:MyCustomNumber) = CN 0
static member ($) (Ring.Add, (CN a)) = fun (CN b) -> CN (a + b)
static member ($) (Ring.Multiply, (CN a)) = fun (CN b) -> CN (a * b)
let z'' : MyCustomNumber = zero()
let s'' = CN 1 <+> CN 2
If you want to scale up with this approach you can have a look at FsControl which already defines Monoid with Zero (Mempty) and Add (Mappend). You can submit a pull request for Ring.
Now to be practical if you are planning to use all this only with numbers why not use GenericNumbers in F#, (+) and (*) are already generic then you have LanguagePrimitives.GenericZero and LanguagePrimitives.GenericOne.
I'm looking for a clean set of ways to manage Test Specific Equality in F# unit tests. 90% of the time, the standard Structural Equality fits the bill and I can leverage it with unquote to express the relation between my result and my expected.
TL;DR "I can't find a clean way to having a custom Equality function for one or two properties in a value which 90% of is well served by Structural Equality, does F# have a way to match an arbitrary record with custom Equality for just one or two of its fields?"
Example of a general technique that works for me
When verifying a function that performs a 1:1 mapping of a datatype to another, I'll often extract matching tuples from both sides of in some cases and compare the input and output sets. For example, I have an operator:-
let (====) x y = (x |> Set.ofSeq) = (y |> Set.ofSeq)
So I can do:
let inputs = ["KeyA",DateTime.Today; "KeyB",DateTime.Today.AddDays(1); "KeyC",DateTime.Today.AddDays(2)]
let trivialFun (a:string,b) = a.ToLower(),b
let expected = inputs |> Seq.map trivialFun
let result = inputs |> MyMagicMapper
test <# expected ==== actual #>
This enables me to Assert that each of my inputs has been mapped to an output, without any superfluous outputs.
The problem
The problem is when I want to have a custom comparison for one or two of the fields.
For example, if my DateTime is being passed through a slightly lossy serialization layer by the SUT, I need a test-specific tolerant DateTime comparison. Or maybe I want to do a case-insensitive verification for a string field
Normally, I'd use Mark Seemann's SemanticComparison library's Likeness<Source,Destination> to define a Test Specific equality, but I've run into some roadblocks:
tuples: F# hides .ItemX on Tuple so I can't define the property via a .With strongly typed field name Expression<T>
record types: TTBOMK these are sealed by F# with no opt-out so SemanticComparison can't proxy them to override Object.Equals
My ideas
All I can think of is to create a generic Resemblance proxy type that I can include in a tuple or record.
Or maybe using pattern matching (Is there a way I can use that to generate an IEqualityComparer and then do a set comparison using that?)
Alternate failing test
I'm also open to using some other function to verify the full mapping (i.e. not abusing F# Set or involving too much third party code. i.e. something to make this pass:
let sut (a:string,b:DateTime) = a.ToLower(),b + TimeSpan.FromTicks(1L)
let inputs = ["KeyA",DateTime.Today; "KeyB",DateTime.Today.AddDays(1.0); "KeyC",DateTime.Today.AddDays(2.0)]
let toResemblance (a,b) = TODO generate Resemblance which will case insensitively compare fst and tolerantly compare snd
let expected = inputs |> List.map toResemblance
let result = inputs |> List.map sut
test <# expected = result #>
Firstly, thanks to all for the inputs. I was largely unaware of SemanticComparer<'T> and it definitely provides a good set of building blocks for building generalized facilities in this space. Nikos' post gives excellent food for thought in the area too. I shouldn't have been surprised Fil exists too - #ptrelford really does have a lib for everything (the FSharpValue point is also v valuable)!
We've thankfully arrived at a conclusion to this. Unfortunately it's not a single all-encompassing tool or technique, but even better, a set of techniques that can be used as necessary in a given context.
Firstly, the issue of ensuring a mapping is complete is really an orthogonal concern. The question refers to an ==== operator:-
let (====) x y = (x |> Set.ofSeq) = (y |> Set.ofSeq)
This is definitely the best default approach - lean on Structural Equality. One thing to note is that, being reliant on F# persistent sets, it requires your type to support : comparison (as opposed to just : equality).
When doing set comparisons off the proven Structural Equality path, a useful technique is to use HashSet<T> with a custom IEqualityComparer:-
[<AutoOpen>]
module UnorderedSeqComparisons =
let seqSetEquals ec x y =
HashSet<_>( x, ec).SetEquals( y)
let (==|==) x y equals =
let funEqualityComparer = {
new IEqualityComparer<_> with
member this.GetHashCode(obj) = 0
member this.Equals(x,y) =
equals x y }
seqSetEquals funEqualityComparer x y
the equals parameter of ==|== is 'a -> 'a -> bool which allows one to use pattern matching to destructure args for the purposes of comparison. This works well if either the input or the result side are naturally already tuples. Example:
sut.Store( inputs)
let results = sut.Read()
let expecteds = seq { for x in inputs -> x.Name,x.ValidUntil }
test <# expecteds ==|== results
<| fun (xN,xD) (yN,yD) ->
xF=yF
&& xD |> equalsWithinASecond <| yD #>
While SemanticComparer<'T> can do a job, it's simply not worth bothering for tuples with when you have the power of pattern matching. e.g. Using SemanticComparer<'T>, the above test can be expressed as:
test <# expecteds ==~== results
<| [ funNamedMemberComparer "Item2" equalsWithinASecond ] #>
using the helper:
[<AutoOpen>]
module MemberComparerHelpers =
let funNamedMemberComparer<'T> name equals = {
new IMemberComparer with
member this.IsSatisfiedBy(request: PropertyInfo) =
request.PropertyType = typedefof<'T>
&& request.Name = name
member this.IsSatisfiedBy(request: FieldInfo) =
request.FieldType = typedefof<'T>
&& request.Name = name
member this.GetHashCode(obj) = 0
member this.Equals(x, y) =
equals (x :?> 'T) (y :?> 'T) }
let valueObjectMemberComparer() = {
new IMemberComparer with
member this.IsSatisfiedBy(request: PropertyInfo) = true
member this.IsSatisfiedBy(request: FieldInfo) = true
member this.GetHashCode(obj) = hash obj
member this.Equals(x, y) =
x.Equals( y) }
let (==~==) x y mcs =
let ec = SemanticComparer<'T>( seq {
yield valueObjectMemberComparer()
yield! mcs } )
seqSetEquals ec x y
All of the above is best understood by reading Nikos Baxevanis' post NOW!
For types or records, the ==|== technique can work (except critically you lose Likeness<'T>s verifying coverage of fields). However the succinctness can make it a valuable tool for certain sorts of tests :-
sut.Save( inputs)
let expected = inputs |> Seq.map (fun x -> Mapped( base + x.ttl, x.Name))
let likeExpected x = expected ==|== x <| (fun x y -> x.Name = y.Name && x.ValidUntil = y.ValidUntil)
verify <# repo.Store( is( likeExpected)) #> once