Does F# support 'call-by-name' semantics? - f#

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))

Related

What is missing using interfaces compared to true type-classes?

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.

Reader monad transformer sample with FSharpPlus

I'm trying to understand the reader monad transformer. I'm using FSharpPlus and try to compile the following sample which first reads something from the reader environment, then performs some async computation and finally combines both results:
open FSharpPlus
open FSharpPlus.Data
let sampleReader = monad {
let! value = ask
return value * 2
}
let sampleWorkflow = monad {
do! Async.Sleep 5000
return 4
}
let doWork = monad {
let! envValue = sampleReader
let! workValue = liftAsync sampleWorkflow
return envValue + workValue
}
ReaderT.run doWork 3 |> Async.RunSynchronously |> printfn "Result: %d"
With this I get a compilation error at the line where it says let! value = ask with the following totally unhelpful (at least for me) error message:
Type constraint mismatch when applying the default type 'obj' for a type inference variable. No overloads match for method 'op_GreaterGreaterEquals'.
Known return type: Async
Known type parameters: < obj , (int -> Async) >
It feels like I'm just missing some operator somewhere, but I can't figure it out.
Your code is correct, but F# type inference is not that smart in cases like this.
If you add a type annotation to sampleReader it will compile fine:
let sampleReader : ReaderT<int,Async<_>> = monad {
let! value = ask
return value * 2
}
// val sampleReader : FSharpPlus.Data.ReaderT<int,Async<int>> =
// ReaderT <fun:sampleReader#7>
Update:
After reading your comments.
If what you want is to make it generic, first of all your function has to be declared inline otherwise type constraints can't be applied:
let inline sampleReader = monad ...
But that takes you to the second problem: a constant can't be declared inline (actually there is a way but it's too complicated) only functions can.
So the easiest is to make it a function:
let inline sampleReader () = monad ...
And now the third problem the code doesn't compile :)
Here again, you can give type inference a minimal hint, just to say at the call site that you expect a ReaderT<_,_> will be enough:
let inline sampleReader () = monad {
let! value = ask
return value * 2
}
let sampleWorkflow = monad {
do! Async.Sleep 5000
return 4
}
let doWork = monad {
let! envValue = sampleReader () : ReaderT<_,_>
let! workValue = liftAsync sampleWorkflow
return envValue + workValue
}
ReaderT.run doWork 3 |> Async.RunSynchronously |> printfn "Result: %d"
Conclusion:
Defining a generic function is not that trivial task in F#.
If you look into the source of F#+ you'll see what I mean.
After running your example you'll see all the constraints being generated and you'll probably noted how the compile-time increased by making your function inline and generic.
These are all indications that we're pushing F# type system to the limits.
Although F#+ defines some ready-to-use generic functions, and these functions can sometimes be combined in such a way that you create your own generic functions, that's not the goal of the library, I mean you can but then you're on your own, in some scenarios like exploratory development it might make sense.

Random / State workflow in F#

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.

Constructing and deconstructing records

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.

F# type constraints and overloading resolution

I am trying to emulate a system of type classes in F#; I would like to create pair printer which automatically instantiates the right series of calls to the printing functions. My latest try, which is pasted here, fails miserably since F# cannot identify the right overload and gives up immediately:
type PrintableInt(x:int) =
member this.Print() = printfn "%d" x
let (!) x = PrintableInt(x)
type Printer() =
static member inline Print< ^a when ^a : (member Print : Unit -> Unit)>(x : ^a) =
(^a : (member Print : Unit -> Unit) x)
static member inline Print((x,y) : 'a * 'b) =
Printer.Print(x)
Printer.Print(y)
let x = (!1,!2),(!3,!4)
Printer.Print(x)
Is there any way to do so? I am doing this in the context of game development, so I cannot afford the runtime overhead of reflection, retyping and dynamic casting: either I do this statically through inlining or I don't do it at all :(
What you're trying to do is possible.
You can emulate typeclasses in F#, as Tomas said maybe is not as idiomatic as in Haskell. I think in your example you are mixing typeclasses with duck-typing, if you want to go for the typeclasses approach don't use members, use functions and static members instead.
So your code could be something like this:
type Print = Print with
static member ($) (_Printable:Print, x:string) = printfn "%s" x
static member ($) (_Printable:Print, x:int ) = printfn "%d" x
// more overloads for existing types
let inline print p = Print $ p
type Print with
static member inline ($) (_Printable:Print, (a,b) ) = print a; print b
print 5
print ((10,"hi"))
print (("hello",20), (2,"world"))
// A wrapper for Int (from your sample code)
type PrintableInt = PrintableInt of int with
static member ($) (_Printable:Print, (PrintableInt (x:int))) = printfn "%d" x
let (!) x = PrintableInt(x)
let x = (!1,!2),(!3,!4)
print x
// Create a type
type Person = {fstName : string ; lstName : string } with
// Make it member of _Printable
static member ($) (_Printable:Print, p:Person) = printfn "%s, %s" p.lstName p.fstName
print {fstName = "John"; lstName = "Doe" }
print (1 ,{fstName = "John"; lstName = "Doe" })
Note: I used an operator to avoid writing the constraints by hand, but in this case is also possible to use a named static member.
More about this technique here.
What you're trying to do is not possible (edit: apparently, it can be done - but it might not be idiomatic F#), because the constraint language cannot capture the constraints you need for the second Print operation. Basically, there is no way to write recursive constraints saying that:
Let C be a constraint specifying that the type either provides Print or it is a two-element tuple where each element satisfies C.
F# does not support type-classes and so most of the attempts to emulate them will (probably) be limited in some way or will look very unnatural. In practice, instead of trying to emulate solutions that work in other languages, it is better to look for an idiomatic F# solution to the problem.
The pretty printing that you're using as a sample would be probably implemented using Reflection or by wrapping not just integers, but also tuples.

Resources