reusing type aliases in type aliases - f#

So I was quite impressed the other day when I saw...
type Foo<'a> =
abstract foo : Unit -> 'a
type IsFoo<'a,'b when 'a :> Foo<'b>> = 'a
(I know this example is a bit daft)
the point being that complex parametric constraints can be captured in a type alias....nice
I then started using this a bit, but I got to a point where I have a function that requires a Bar
type Bar<'b> =
abstract bar : Unit -> 'b
and so we have
type IsBar<'a,'b when 'a :> Bar<'b>> = 'a
but then I wanted a Foo that returned a Bar....so I COULD go....(I think)
type IsFooThenBar<'a,'b,'c when 'a :> Foo<'b> and 'b :> Bar<'c>> =
IsFoo<'a,IsBar<'b,'c>>
but this is sort of just a restatement of stuff I already know...really I'd quite like the constraint to be inferred i.e.
type IsFooThenBar2<'a,'b,'c> = IsFoo<'a,IsBar<'b,'c>>
but that clearly doesnt work because the compiler complains I cant assert IsFoo and IsBar unless I have the required contraints...
any ideas?....I have lots of generic constraints on my code, and these don't really play nicely with type declarations.
to clarify based on some feedback, how can I take a set of type aliases and compose them into more complex ones without simply restating them....i.e. I want to be able to ammend one of the axiomatic aliases, and that be reflectied into derived aliases, without lots and lots and lots of typing.
so making this concrete, I can write
let f (x : IsFoo<_,IsBar<_,string>>) =
x.foo().bar()
which in simple cases is OK...but remember I have lots and lots of parameters...
so I really want to simplify this and write...
let f2 (x : IsFooThenBar<_,_,string>) =
x.foo().bar()
and I can of course do that if I define IsFooThenBar as described above....
i.e. type aliases give me the mechanism I want, but there seems to be no simple way to compose type aliases without restating all the constraints in the top level alias.
thats fine in this case....but for large numbers of parameters, it becomes more and more onerous.
So...an example of a language where you can do this sort of thing is Haskell...
> class Foo a b | a -> b where
> foo :: a -> b
>
> class Bar a b | a -> b where
> bar :: a -> b
> class (Foo foo bar,Bar bar a) => FooThenBar foo bar a where
I can then use FooThenBar as short hand for saying that there exists functions that map a 'foo to a 'bar and a 'bar to whatever type I specify
(I'm not Haskell expert and had to get help to create this loosely equivalent scenario)
this is the original function
> f :: (Bar bar b, Foo foo bar) => foo -> b
> f x = bar (foo x)
and this uses the new inferred composition
> f' :: (FooThenBar foo bar b) => foo -> b
> f' x = bar (foo x)

Related

Make Fish in F#

The Kleisli composition operator >=>, also known as the "fish" in Haskell circles, may come in handy in many situations where composition of specialized functions is needed. It works kind of like the >> operator, but instead of composing simple functions 'a -> 'b it confers some special properties on them possibly best expressed as 'a -> m<'b>, where m is either a monad-like type or some property of the function's return value.
Evidence of this practice in the wider F# community can be found e.g. in Scott Wlaschin's Railway oriented programming (part 2) as composition of functions returning the Result<'TSuccess,'TFailure> type.
Reasoning that where there's a bind, there must be also fish, I try to parametrize the canonical Kleisli operator's definition let (>=>) f g a = f a >>= g with the bind function itself:
let mkFish bind f g a = bind g (f a)
This works wonderfully with the caveat that generally one shouldn't unleash special operators on user-facing code. I can compose functions returning options...
module Option =
let (>=>) f = mkFish Option.bind f
let odd i = if i % 2 = 0 then None else Some i
let small i = if abs i > 10 then None else Some i
[0; -1; 9; -99] |> List.choose (odd >=> small)
// val it : int list = [-1; 9]
... or I can devise a function application to the two topmost values of a stack and push the result back without having to reference the data structure I'm operating on explicitly:
module Stack =
let (>=>) f = mkFish (<||) f
type 'a Stack = Stack of 'a list
let pop = function
| Stack[] -> failwith "Empty Stack"
| Stack(x::xs) -> x, Stack xs
let push x (Stack xs) = Stack(x::xs)
let apply2 f =
pop >=> fun x ->
pop >=> fun y ->
push (f x y)
But what bothers me is that the signature val mkFish : bind:('a -> 'b -> 'c) -> f:('d -> 'b) -> g:'a -> a:'d -> 'c makes no sense. Type variables are in confusing order, it's overly general ('a should be a function), and I'm not seeing a natural way to annotate it.
How can I abstract here in the absence of formal functors and monads, not having to define the Kleisli operator explicitly for each type?
You can't do it in a natural way without Higher Kinds.
The signature of fish should be something like:
let (>=>) (f:'T -> #Monad<'U>``) (g:' U -> #Monad<'V>) (x:'T) : #Monad<'V> = bind (f x) g
which is unrepresentable in current .NET type system, but you can replace #Monad with your specific monad, ie: Async and use its corresponding bind function in the implementation.
Having said that, if you really want to use a generic fish operator you can use F#+ which has it already defined by using static constraints. If you look at the 5th code sample here you will see it in action over different types.
Of course you can also define your own, but there is a lot of things to code, in order to make it behave properly in most common scenarios. You can grab the code from the library or if you want I can write a small (but limited) code sample.
The generic fish is defined in this line.
I think in general you really feel the lack of generic functions when using operators, because as you discovered, you need to open and close modules. It's not like functions that you prefix them with the module name, you can do that with operators as well (something like Option.(>=>)) , but then it defeats the whole purpose of using operators, I mean it's no longer an operator.

Free Monad in F# with generic output type

I am trying to apply the free monad pattern as described in F# for fun and profit to implement data access (for Microsoft Azure Table Storage)
Example
Let's assume we have three database tables and three dao's Foo, Bar, Baz:
Foo Bar Baz
key | col key | col key | col
--------- --------- ---------
foo | 1 bar | 2 |
I want to select Foo with key="foo" and Bar with key="bar" to insert a Baz with key="baz" and col=3
Select<Foo> ("foo", fun foo -> Done foo)
>>= (fun foo -> Select<Bar> ("bar", fun bar -> Done bar)
>>= (fun bar -> Insert<Baz> ((Baz ("baz", foo.col + bar.col), fun () -> Done ()))))
Within the interpreter function
Select results in a function call that takes a key : string and returns an obj
Insert results in a function call that takes an obj and returns unit
Problem
I defined two operations Select and Insert in addition to Done to terminate the computation:
type StoreOp<'T> =
| Select of string * ('T -> StoreOp<'T>)
| Insert of 'T * (unit -> StoreOp<'T>)
| Done of 'T
In order to chain StoreOp's I am trying to implement the correct bind function:
let rec bindOp (f : 'T1 -> StoreOp<'T2>) (op : StoreOp<'T1>) : StoreOp<'T2> =
match op with
| Select (k, next) ->
Select (k, fun v -> bindOp f (next v))
| Insert (v, next) ->
Insert (v, fun () -> bindOp f (next ()))
| Done t ->
f t
let (>>=) = bindOp
However, the f# compiler correctly warns me that:
The type variable 'T1 has been constrained to be type 'T2
For this implementation of bindOp the type is fixed throughout the computation, so instead of:
Foo > Bar > unit
all I can express is:
Foo > Foo > Foo
How should I modify the definition of StoreOp and/or bindOp to work with different types throughout the computation?
As Fyodor mentioned in the comments, the problem is with the type declaration. If you wanted to make it compile at the price of sacrificing type safety, you could use obj in two places - this at least shows where the problem is:
type StoreOp<'T> =
| Select of string * (obj -> StoreOp<'T>)
| Insert of obj * (unit -> StoreOp<'T>)
| Done of 'T
I'm not entirely sure what the two operations are supposed to model - but I guess Select means you are reading something (with string key?) and Insert means that you are storing some value (and then continue with unit). So, here, the data you are storing/reading would be obj.
There are ways of making this type safe, but I think you'd get better answer if you explained what are you trying to achieve by using the monadic structure.
Without knowing more, I think using free monads will only make your code very messy and difficult to understand. F# is a functional-first language, which means that you can write data transformations in a nice functional style using immutable data types and use imperative programming to load your data and store your results. If you are working with table storage, why not just write the normal imperative code to read data from table storage, pass the results to a pure functional transformation and then store the results?

constrain generic type to inherit a generic type in f#

let mapTuple f (a,b) = (f a, f b)
I'm trying to create a function that applies a function f to both items in a tuple and returns the result as a tuple. F# type inference says that mapTuple returns a 'b*'b tuple. It also assumes that a and b are of the same type.
I want to be able to pass two different types as parameters. You would think that wouldn't work because they both have to be passed as parameters to f. So I thought if they inherited from the same base class, it might work.
Here is a less generic function for what I am trying to accomplish.
let mapTuple (f:Map<_,_> -> Map<'a,'b>) (a:Map<int,double>,b:Map<double, int>) = (f a, f b)
However, it gives a type mismatch error.
How do I do it? Is what I am trying to accomplish even possible in F#?
Gustavo is mostly right; what you're asking for requires higher-rank types. However,
.NET (and by extension F#) does support (an encoding of) higher-rank types.
Even in Haskell, which supports a "nice" way of expressing such types (once you've enabled the right extension), they wouldn't be inferred for your example.
Digging into point 2 may be valuable: given map f a b = (f a, f b), why doesn't Haskell infer a more general type than map :: (t1 -> t) -> t1 -> t1 -> (t, t)? The reason is that once you include higher-rank types, it's not typically possible to infer a single "most general" type for a given expression. Indeed, there are many possible higher-rank signatures for map given its simple definition above:
map :: (forall t. t -> t) -> x -> y -> (x, y)
map :: (forall t. t -> z) -> x -> y -> (z, z)
map :: (forall t. t -> [t]) -> x -> y -> ([x], [y])
(plus infinitely many more). But note that these are all incompatible with each other (none is more general than another). Given the first one you can call map id 1 'c', given the second one you can call map (\_ -> 1) 1 'c', and given the third one you can call map (\x -> [x]) 1 'c', but those arguments are only valid with each of those types, not with the other ones.
So even in Haskell you need to specify the particular polymorphic signature you want to use - this may be a bit of a surprise if you're coming from a more dynamic language. In Haskell, this is relatively clean (the syntax is what I've used above). However, in F# you'll have to jump through an additional hoop: there's no clean syntax for a "forall" type, so you'll have to create an additional nominal type instead. For example, to encode the first type above in F# I'd write something like this:
type Mapping = abstract Apply : 'a -> 'a
let map (m:Mapping) (a, b) = m.Apply a, m.Apply b
let x, y = map { new Mapping with member this.Apply x = x } (1, "test")
Note that in contrast to Gustavo's suggestion, you can define the first argument to map as an expression (rather than forcing it to be a member of some separate type). On the other hand, there's clearly a lot more boilerplate than would be ideal...
This problem has to do with rank-n types which are supported in Haskell (through extensions) but not in .NET type system.
One way I found to workaround this limitation is to pass a type with a single method instead of a function and then define an inline map function with static constraints, for example let's suppose I have some generic functions: toString and toOption and I want to be able to map them to a tuple of different types:
type ToString = ToString with static member inline ($) (ToString, x) = string x
type ToOption = ToOption with static member ($) (ToOption, x) = Some x
let inline mapTuple f (x, y) = (f $ x, f $ y)
let tuple1 = mapTuple ToString (true, 42)
let tuple2 = mapTuple ToOption (true, 42)
// val tuple1 : string * string = ("True", "42")
// val tuple2 : bool option * int option = (Some true, Some 42)
ToString will return the same type but operating with arbitrary types. ToOption will return two Generics of different types.
By using a binary operator type inference creates the static constraints for you and I use $ because in Haskell it means apply so a nice detail is that for haskellers f $ x reads already apply x to f.
At the risk of stating the obvious, a good enough solution might be to have a mapTuple that takes two functions instead of one:
let mapTuple fa fb (a, b) = (fa a, fb b)
If your original f is generic, passing it as fa and fb will give you two concrete instantiations of the function with the types you're looking for. At worst, you just need to pass the same function twice when a and b are of the same type.

Type inference wants explicit upcast sometimes even when flexible type is used for interface constraints?

I had expected that flexible type would minimize the need of explicit upcast, but
type IB =
abstract B : int
type A() =
interface IB with
member this.B = 1
let a = A()
let test (x) = x
let aa = [|a; a|]
let case1 = aa |> Array.map (fun (x: #IB) -> test (x.B))
let case2 = Array.map (fun (x: #IB) -> test (x.B)) aa
Here, there are warnings (less generic than type annotation) on the last 2 lines. The compiler is able to compile case2, but fails at case1, why is that?
It feels odd that the more detailed the compiler can infer, the more code I need to write.
#kvb pointed out there is a simple fix, just to refactor the lambda function into a non inline version.
let fix (x: #IB) =
test x.B
let case1 = aa |> Array.map fix
let case2 = Array.map fix
This works well.
Type inference in F# flows from left to right, so it's not too surprising that piping can break or fix things. However, it's almost always the case that having more type information earlier is helpful, so this result is a bit surprising. The warnings are a subtle indicator that you're doing something wrong. Flexible types seem like they ought to be applicable in many tricky situations, but there are really only a few places where they help. Array.map takes a function of some type 'a -> 'b for some particular 'a and 'b (though there's a little bit of nuance here, since the "particular" types could be type variables), so having a "more generic" argument like #IB -> int is not especially helpful; the compiler will pick some particular subtype of IB during compilation - this is what the warnings are attempting to communicate.
As I said, the different results you see on the different lines are due to the fact that type inference in F# works left to right. In the first case, the information about the type of aa flows into the type checking of the remainder of the expression and so when compiling the lambda the compiler knows that the only possible subtype of IB that will work is A, but because interface implementations are always implicit this causes a compile time error because A doesn't have a publicly available member B. On the other hand, in the second case, when the compiler's trying to check Array.map it doesn't yet know the type of the array it will be applied to, but can check the call in any case because regardless of the subtype it will support the interface method IB.B (implicitly upcasting the argument from whatever subtype of IB it has to just IB). Then when this is applied to aa the compiler specializes the implementation to A, but because of the implicit upcast this still works okay. Intuitively, it seems like the compiler ought to have been able to have inserted the same implicit upcast in the former case, but I think this is probably just a surprising result of the inference algorithm and not an actual bug.
Perhaps more surprising, one possible fix is to just use a let-bound definition (for either the lambda or even as a type-restricted version of Array.map) and skip the flexible type:
let f (x:IB) = test (x.B)
let g (f:IB -> int) = Array.map f
let d' = aa |> g (fun x -> test (x.B))
let d'' = aa |> Array.map f
let c' = g (fun x -> test (x.B)) aa
let c'' = Array.map f aa
So what's happening here? It turns out the compiler does something called "Implicit Insertion of Flexibility for Uses of Functions and Members" (section 14.4.3 of the spec for F# 3.1) which does exactly what you want.
type IB =
abstract B : int
type A() =
interface IB with
member this.B = 1
let a = A()
let test (x) = x
let aa = [|a; a|]
Here the compiler knows that aa is an array of A so type annotation in lambda is not needed but you have to cast x to the interface type because in F# interfaces are implemented explicitely (http://msdn.microsoft.com/en-us/library/ms173157.aspx):
let d = aa |> Array.map (fun x -> test ((x:>IB).B))
Here the compiler at the moment of compiling lambda doesn't know what a type of x is, so you need a type annotation telling that x is implementation of IB interface so you can refer to x.B property directly:
let c = Array.map (fun (x: #IB) -> test (x.B)) aa

How to implicitly convert to common super types in F# pattern matches?

Problem Summary
At the moment when using f# I must explicitly coerce a value to the parent type of its type in order to get pattern matching expressions to type check correctly. I would ideally like a neater way of doing.
Example
Suppose I have some class hierachy:
type Foo () =
abstract member Value : unit -> string
type A (i:int) =
inherit Foo ()
override this.Value () = i.ToString()
type B (s:string) =
inherit Foo ()
override this.Value () = s
Ideally, and in some programming languages in normally, I would write the equivalent of the following:
let bar (i:int) : Foo =
match i with
| 1 -> B "one"
| _ -> A i
However this fails to type check correctly, giving me the error, "This expression was expected to have type Foo but here has type B". I don't understand why the compiler doesn't have enough information to infer a common super type for the match expression and then check that the common super type is 'Foo'.
At present I am forced to provide an explicit coercion for every case in the pattern match:
let bar2 (i:int) : Foo =
match i with
| 1 -> (B "one") :> Foo
| _ -> (A i) :> Foo
I would like to avoid this.
Further Notes
Intuition suggests that this is a result of a more general issue. I would have thought though that something as common as pattern matching, or if statements which also exhibit the same property, would have a type checking rule to account for common super types.
Before anyone suggests - I appreciate that if A or B were Object Expressions this would work, but my real example is creating instances of C# classes where they are normal classes.
Is there a way for me to declare functions to implicitly convert types, as for example scala has, so I could apply automatic conversions for the module where I'm doing this generation?
Thanks for any help on this matter.
I would use upcast, a la
[<AbstractClass>]
type Foo () =
abstract member Value : unit -> string
type A (i:int) =
inherit Foo ()
override this.Value () = i.ToString()
type B (s) =
inherit Foo ()
override this.Value () = s
let bar2 i : Foo =
match i with
| 1 -> upcast B "one"
| _ -> upcast A i
You still have to add it to every branch, but this is often preferable to casting to the type, since often the typename is like 20 or 30 characters long (MyNamespace.ThisThingy), whereas upcast is just 6 characters.
But, briefly, the language rules don't allow for anything else, the types of all the branches have to be equal.
I've seen this question a couple of times before, but I just realized that there is quite an interesting way to workaround the issue (without any significant negative effects such as big runtime overhead).
You can use a very simple computation expression that has only Return member. The builder will have a type parameter and Return will expect values of this type. The trick is, that F# does insert automatic upcasts when calling a member. Here is the declaration:
type ExprBuilder<'T>() =
member x.Return(v:'T) = v
let expr<'T> = ExprBuilder<'T>()
To write a simple pattern matching that returns anything as obj, you can now write:
let foo a = expr<obj> {
match a with
| 0 -> return System.Random()
| _ -> return "Hello" }
You still have to be explicit about the return type (when creating the computation expression), but I find the syntax quite neat (but it is definitely a tricky use that could confuse people who'll see it for the first time).

Resources