Recursive discriminated unions and map - recursion

I need a type of tree and a map on those, so I do this:
type 'a grouping =
G of ('a * 'a grouping) list
with
member g.map f =
let (G gs) = g
gs |> List.map (fun (s, g) -> f s, g.map f) |> G
But this makes me wonder:
The map member is boilerplate. In Haskell, GHC would implement fmap for me (... deriving (Functor)). I know F# doesn't have typeclasses, but is there some other way I can avoid writing map myself in F#?
Can I somehow avoid the line let (G gs) = g?
Is this whole construction somehow non-idiomatic? It looks weird to me, but maybe that's just because putting members on sum types is new to me.

I don't think there is a way to derive automatically map, however there's a way to emulate type classes in F#, your code can be written like this:
#r #"FsControl.Core.dll"
#r #"FSharpPlus.dll"
open FSharpPlus
open FsControl.Core.TypeMethods
type 'a grouping =
G of ('a * 'a grouping) list
with
// Add an instance for Functor
static member instance (_:Functor.Map, G gs, _) = fun (f:'b->'c) ->
map (fun (s, g) -> f s, map f g) gs |> G
// TEST
let a = G [(1, G [2, G[]] )]
let b = map ((+) 10) a // G [(11, G [12, G[]] )]
Note that map is really overloaded, the first application you see calls the instance for List<'a> and the second one the instance for grouping<'a>. So it behaves like fmap in Haskell.
Also note this way you can decompose G gs without creating the let (G gs) = g
Now regarding what is idiomatic I think many people would agree your solution is more F# idiomatic, but to me new idioms should also be developed in order to get more features and overcome current language limitations, that's why I consider using a library which define clear conventions also idiomatic.
Anyway I agree with #kvb in that it's slightly more idiomatic to define map into a module, in F#+ that convention is also used, so you have the generic map and the specific ModuleX.map

Related

Do pure functions have only one possible implementation?

In the image below there is a quick explanation, why pure functions appear to have only one possible implementation.I don't really get the idea because (++) : ('a -> 'b) -> ('a -> 'b) -> 'a -> 'b for example can clearly be implemented by let (++) (f: ('a -> 'b)) (g: ('a -> 'b)) x = f x orlet (++) (f: ('a -> 'b)) (g: ('a -> 'b)) x = g x
Is that image just wrong or do I miss something here?
You are right. The attached image is incorrect even without type annotations.
At first, it's important to consider what kind of "equality" on implementations is assumed here. Let's consider the following examples.
Is (##) equal to (##+)?
let ( ## ) f x = f x
let ( ##+ ) f x =
let _ = 42 in
f x
Is (|>) equal to (|>+)?
let ( |> ) x f = f x
let ( |>+ ) x f = f ## x
Is (%) equal to (%+)?
let ( % ) f g x = f (g x)
let ( %+ ) p q r = p (q r)
If (##) is not equal to (##+), then we can construct the 5th implementation of a function bool -> bool, such as (fun x -> let _ = 42 in true).
Therefore, the author of the image would have wanted to distinguish functions not by its implementation (or codes), but by some other element such as its behavior (like duck test or the equality on mathematical functions).
Still, the image is incorrect. The image claims "for pure functions that don't have any concrete type in the signature, there is only one possible implementation", but no. For example, there is no pure function 'a -> 'b. This can be shown through the Curry–Howard correspondence.
The image is wrong if you consider the counterexample you just gave. I think the author of the image didn’t consider the possibility of type annotation.
In fact if
there are no type annotations and
all the arguments are polymorphic and or function over polymorphic types,
you don’t consider the existence of polymorphic operators such as = or <>
(otherwise it is wrong since <> and = have the same type and different implementation),
then there is only one pure implementation of your function signature.
(you can probably prove that by saying the only things you can use to define that function are :
pure functions of the same type, that can be inlined, so you can ignore that
match-patterns and let, for which the image’s argument is true
cartesian product (let f a b = a, b)
function composition
infinite recursion
and maybe other things I forget, but you can make an exhaustive list
and that the combination of these used can be guessed from the output and input types.
)

F# - Treating a function like a map

Long story short, I came up with this funny function set, that takes a function, f : 'k -> 'v, a chosen value, k : 'k, a chosen result, v : 'v, uses f as the basis for a new function g : 'k -> 'v that is the exact same as f, except for that it now holds that, g k = v.
Here is the (pretty simple) F# code I wrote in order to make it:
let set : ('k -> 'v) -> 'k -> 'v -> 'k -> 'v =
fun f k v x ->
if x = k then v else f x
My questions are:
Does this function pose any problems?
I could imagine repeat use of the function, like this
let kvs : (int * int) List = ... // A very long list of random int pairs.
List.fold (fun f (k,v) -> set f k v) id kvs
would start building up a long list of functions on the heap. Is this something to be concerned about?
Is there a better way to do this, while still keeping the type?
I mean, I could do stuff like construct a type for holding the original function, f, a Map, setting key-value pairs to the map, and checking the map first, the function second, when using keys to get values, but that's not what interests me here - what interest me is having a function for "modifying" a single result for a given value, for a given function.
Potential problems:
The set-modified function leaks space if you override the same value twice:
let huge_object = ...
let small_object = ...
let f0 = set f 0 huge_object
let f1 = set f0 0 small_object
Even though it can never be the output of f1, huge_object cannot be garbage-collected until f1 can: huge_object is referenced by f0, which is in turn referenced by the f1.
The set-modified function has overhead linear in the number of set operations applied to it.
I don't know if these are actual problems for your intended application.
If you wish set to have exactly the type ('k -> 'v) -> 'k -> 'v -> 'k -> 'v then I don't see a better way(*). The obvious idea would be to have a "modification table" of functions you've already modified, then let set look up a given f in this table. But function types do not admit equality checking, so you cannot compare f to the set of functions known to your modification table.
(*) Reflection not withstanding.

Limitations of let rec in OCaml

I'm studying OCaml these days and came across this:
OCaml has limits on what it can put on the righthand side of a let rec. Like this one
let memo_rec f_norec =
let rec f = memoize (fun x -> f_norec f x) in
f;;
Error: This kind of expression is not allowed as right-hand side of `let rec'
in which, the memoize is a function that take a function and turns it into a memorized version with Hashtable. It's apparent that OCaml has some restriction on the use of constructs at the right-hand side of 'let rec', but I don't really get it, could anyone explain a bit more on this?
The kind of expressions that are allowed to be bound by let rec are described in section 8.1 of the manual. Specifically, function applications involving the let rec defined names are not allowed.
A rough summary (taken from that very link):
Informally, the class of accepted definitions consists of those definitions where the defined names occur only inside function bodies or as argument to a data constructor.
You can use tying-the-knot techniques to define memoizing fixpoints. See for example those two equivalent definitions:
let fix_memo f =
let rec g = {contents = fixpoint}
and fixpoint x = f !g x in
g := memoize !g;
!g
let fix_memo f =
let g = ref (fun _ -> assert false) in
g := memoize (fun x -> f !g x);
!g
Or using lazy as reminded by Alain:
let fix_memo f =
let rec fix = lazy (memoize (fun x -> f (Lazy.force fix) x)) in
Lazy.force fix

OCaml: Is there a function with type 'a -> 'a other than the identity function?

This isn't a homework question, by the way. It got brought up in class but my teacher couldn't think of any. Thanks.
How do you define the identity functions ? If you're only considering the syntax, there are different identity functions, which all have the correct type:
let f x = x
let f2 x = (fun y -> y) x
let f3 x = (fun y -> y) (fun y -> y) x
let f4 x = (fun y -> (fun y -> y) y) x
let f5 x = (fun y z -> z) x x
let f6 x = if false then x else x
There are even weirder functions:
let f7 x = if Random.bool() then x else x
let f8 x = if Sys.argv < 5 then x else x
If you restrict yourself to a pure subset of OCaml (which rules out f7 and f8), all the functions you can build verify an observational equation that ensures, in a sense, that what they compute is the identity : for all value f : 'a -> 'a, we have that f x = x
This equation does not depend on the specific function, it is uniquely determined by the type. There are several theorems (framed in different contexts) that formalize the informal idea that "a polymorphic function can't change a parameter of polymorphic type, only pass it around". See for example the paper of Philip Wadler, Theorems for free!.
The nice thing with those theorems is that they don't only apply to the 'a -> 'a case, which is not so interesting. You can get a theorem out of the ('a -> 'a -> bool) -> 'a list -> 'a list type of a sorting function, which says that its application commutes with the mapping of a monotonous function.
More formally, if you have any function s with such a type, then for all types u, v, functions cmp_u : u -> u -> bool, cmp_v : v -> v -> bool, f : u -> v, and list li : u list, and if cmp_u u u' implies cmp_v (f u) (f u') (f is monotonous), you have :
map f (s cmp_u li) = s cmp_v (map f li)
This is indeed true when s is exactly a sorting function, but I find it impressive to be able to prove that it is true of any function s with the same type.
Once you allow non-termination, either by diverging (looping indefinitely, as with the let rec f x = f x function given above), or by raising exceptions, of course you can have anything : you can build a function of type 'a -> 'b, and types don't mean anything anymore. Using Obj.magic : 'a -> 'b has the same effect.
There are saner ways to lose the equivalence to identity : you could work inside a non-empty environment, with predefined values accessible from the function. Consider for example the following function :
let counter = ref 0
let f x = incr counter; x
You still that the property that for all x, f x = x : if you only consider the return value, your function still behaves as the identity. But once you consider side-effects, you're not equivalent to the (side-effect-free) identity anymore : if I know counter, I can write a separating function that returns true when given this function f, and would return false for pure identity functions.
let separate g =
let before = !counter in
g ();
!counter = before + 1
If counter is hidden (for example by a module signature, or simply let f = let counter = ... in fun x -> ...), and no other function can observe it, then we again can't distinguish f and the pure identity functions. So the story is much more subtle in presence of local state.
let rec f x = f (f x)
This function never terminates, but it does have type 'a -> 'a.
If we only allow total functions, the question becomes more interesting. Without using evil tricks, it's not possible to write a total function of type 'a -> 'a, but evil tricks are fun so:
let f (x:'a):'a = Obj.magic 42
Obj.magic is an evil abomination of type 'a -> 'b which allows all kinds of shenanigans to circumvent the type system.
On second thought that one isn't total either because it will crash when used with boxed types.
So the real answer is: the identity function is the only total function of type 'a -> 'a.
Throwing an exception can also give you an 'a -> 'a type:
# let f (x:'a) : 'a = raise (Failure "aaa");;
val f : 'a -> 'a = <fun>
If you restrict yourself to a "reasonable" strongly normalizing typed λ-calculus, there is a single function of type ∀α α→α, which is the identity function. You can prove it by examining the possible normal forms of a term of this type.
Philip Wadler's 1989 article "Theorems for Free" explains how functions having polymorphic types necessarily satisfy certain theorems (e.g. a map-like function commutes with composition).
There are however some nonintuitive issues when one deals with much polymorphism. For instance, there is a standard trick for encoding inductive types and recursion with impredicative polymorphism, by representing an inductive object (e.g. a list) using its recursor function. In some cases, there are terms belonging to the type of the recursor function that are not recursor functions; there is an example in §4.3.1 of Christine Paulin's PhD thesis.

Higher-order type constructors and functors in Ocaml

Can the following polymorphic functions
let id x = x;;
let compose f g x = f (g x);;
let rec fix f = f (fix f);; (*laziness aside*)
be written for types/type constructors or modules/functors? I tried
type 'x id = Id of 'x;;
type 'f 'g 'x compose = Compose of ('f ('g 'x));;
type 'f fix = Fix of ('f (Fix 'f));;
for types but it doesn't work.
Here's a Haskell version for types:
data Id x = Id x
data Compose f g x = Compose (f (g x))
data Fix f = Fix (f (Fix f))
-- examples:
l = Compose [Just 'a'] :: Compose [] Maybe Char
type Natural = Fix Maybe -- natural numbers are fixpoint of Maybe
n = Fix (Just (Fix (Just (Fix Nothing)))) :: Natural -- n is 2
-- up to isomorphism composition of identity and f is f:
iso :: Compose Id f x -> f x
iso (Compose (Id a)) = a
Haskell allows type variables of higher kind. ML dialects, including Caml, allow type variables of kind "*" only. Translated into plain English,
In Haskell, a type variable g can correspond to a "type constructor" like Maybe or IO or lists. So the g x in your Haskell example would be OK (jargon: "well-kinded") if for example g is Maybe and x is Integer.
In ML, a type variable 'g can correspond only to a "ground type" like int or string, never to a type constructor like option or list. It is therefore never correct to try to apply a type variable to another type.
As far as I'm aware, there's no deep reason for this limitation in ML. The most likely explanation is historical contingency. When Milner originally came up with his ideas about polymorphism, he worked with very simple type variables standing only for monotypes of kind *. Early versions of Haskell did the same, and then at some point Mark Jones discovered that inferring the kinds of type variables is actually quite easy. Haskell was quickly revised to allow type variables of higher kind, but ML has never caught up.
The people at INRIA have made a lot of other changes to ML, and I'm a bit surprised they've never made this one. When I'm programming in ML, I might enjoy having higher-kinded type variables. But they aren't there, and I don't know any way to encode the kind of examples you are talking about except by using functors.
You can do something similar in OCaml, using modules in place of types, and functors (higher-order modules) in place of higher-order types. But it looks much uglier and it doesn't have type-inference ability, so you have to manually specify a lot of stuff.
module type Type = sig
type t
end
module Char = struct
type t = char
end
module List (X:Type) = struct
type t = X.t list
end
module Maybe (X:Type) = struct
type t = X.t option
end
(* In the following, I decided to omit the redundant
single constructors "Id of ...", "Compose of ...", since
they don't help in OCaml since we can't use inference *)
module Id (X:Type) = X
module Compose
(F:functor(Z:Type)->Type)
(G:functor(Y:Type)->Type)
(X:Type) = F(G(X))
let l : Compose(List)(Maybe)(Char).t = [Some 'a']
module Example2 (F:functor(Y:Type)->Type) (X:Type) = struct
(* unlike types, "free" module variables are not allowed,
so we have to put it inside another functor in order
to scope F and X *)
let iso (a:Compose(Id)(F)(X).t) : F(X).t = a
end
Well... I'm not an expert of higher-order-types nor Haskell programming.
But this seems to be ok for F# (which is OCaml), could you work with these:
type 'x id = Id of 'x;;
type 'f fix = Fix of ('f fix -> 'f);;
type ('f,'g,'x) compose = Compose of ('f ->'g -> 'x);;
The last one I wrapped to tuple as I didn't come up with anything better...
You can do it but you need to make a bit of a trick:
newtype Fix f = In{out:: f (Fix f)}
You can define Cata afterwards:
Cata :: (Functor f) => (f a -> a) -> Fix f -> a
Cata f = f.(fmap (cata f)).out
That will define a generic catamorphism for all functors, which you can use to build your own stuff. Example:
data ListFix a b = Nil | Cons a b
data List a = Fix (ListFix a)
instance functor (ListFix a) where
fmap f Nil = Nil
fmap f (Cons a lst) = Cons a (f lst)

Resources