Function signatures - f#

I would like to create a function map3 that, given a function f and a tuple (a, b, c) applies f to every member of the tuple. The expected signature of the function should be:
('a -> 'b) -> 'a * 'a * 'a -> 'b * 'b * 'b .
I tried several approaches:
> let map3 = fun x -> let f = fun (a, b, c) -> (a, b, c) in f x;;
val map3 : 'a * 'b * 'c -> 'a * 'b * 'c
> let map3 = fun x y -> x (let f = fun (a, b, c) -> (a, b, c) in f y);;
val map3 : x:('a * 'b * 'c -> 'd) -> 'a * 'b * 'c -> 'd
> let map3 = fun (x, y, z) -> let f = fun (a, b, c) -> (a, b, c) in f (x, y, z);;
val map3 : x:'a * y:'b * z:'c -> 'a * 'b * 'c
I strongly suspect that I did not get how function signatures actually work. According to what I get, map3 should have one input and one output, and f should take as input a triple and return a triple. But it is clearly wrong on something. What am I missing, in my attempts to implement it?

let map3 f (x, y, z) = (f x, f y, f z)
you can also write it like
let map3 f = fun (x, y, z) -> (f x, f y, f z)
or
let map3 = fun f (x, y, z) -> (f x, f y, f z)
But I would prefer to have the parameters on the left side. As you can see the first version is shorter to write and easier to read.

Related

Is there a more F# idiomatic way to create all combinations from two sequences

I have the following code:
let orders = Array2D.init<AnalyzerOrder> (sentimentRanges |> Seq.length) (triggerRanges |> Seq.length) (fun x y -> AnalyzerOrder.empty)
sentimentRanges |> Seq.iteri (fun x sentimentPeriod ->
triggerRanges |> Seq.iteri (fun y triggerPeriod ->
(
let settings =
{
...
}
orders.[x, y] <- settings
)
)
)
It takes 2 sequences, and create an order list with all the combinations and put them in a grid.
Is there a built-in way to create all the combinations from 2 sequences?
When you look at the implementation of Seq.allPairs you will discover that it boils down to Seq.collect for the outer loop and Seq.cache/Seq.map for the inner. This can be generalized to two functions mapc/iterc, who take a function f:('a -> 'b -> 'c) or action f:('a -> 'b -> unit) as their first argument.
let mapc f xs ys = Seq.collect (fun x -> Seq.map (f x) (Seq.cache ys)) xs
// val mapc : f:('a -> 'b -> 'c) -> xs:seq<'a> -> ys:seq<'b> -> seq<'c>
let iterc f xs ys = Seq.iter (fun x -> Seq.iter (f x) (Seq.cache ys)) xs
// val iterc : f:('a -> 'b -> unit) -> xs:seq<'a> -> ys:seq<'b> -> unit
We could use them to generate the hyperinflation sequence for banknotes (OEIS A051109), or - more to the question - imperatively fill the values of an [,].
mapc (*) (Seq.initInfinite (pown 10I)) [1I; 2I; 5I] |> Seq.take 10 |> Seq.toList
// val it : System.Numerics.BigInteger list =
// [1; 2; 5; 10; 20; 50; 100; 200; 500; 1000]
let a2 = Array2D.zeroCreate 3 3
iterc (fun i j -> a2.[i,j] <- 1) [0..2] [0..2]
An example:
let initArray f s1 s2 = Array2D.init (Array.length s1) (Array.length s2) (fun a b -> f s1.[a] s2.[b] )
initArray (+) [|1;2;3|] [|1;2;3;4|] //where f is a sum function in this case
If you just to list all combinations, you can use the built-in function Seq.allPairs (exists in Array and List variants as well). If you want to create a two-dimensional array, you should do as #FRocha suggests.

Church Numerals in F#

I have been trying to implement church numerals in F#. They were briefly introduced in a course at college and I may have gone down the rabbit hole a bit since then. I have working Predecessor, Successor, Add and Operations but I can't get subtract to work. I'm trying to implement subtract b applying predecessor multiple times. What I find peculiar is that the penultimate line in my code works but what I assume is equivalent, the last line, does not work. There is a type mismatch.
I'm very new to F# so any help would be appreciated. Thank you.
//Operations on tuples
let fst (a,b) = a
let snd (a,b) = b
let pair a b = (a,b)
//Some church numerals
let c0 (f:('a -> 'a)) = id
let c1 (f:('a -> 'a)) = f
let c2 f = f << f
let c3 f = f << f << f
let c4 f = f << f << f << f
// Successor and predecessor
let cSucc (b,(cn:('a->'a)->('a->'a))) = if b then (b, fun f -> f << (cn f)) else (true, fun f -> (cn f))
let cPred (cn:('a->'a)->('a->'a)) = fun f -> snd (cn cSucc (false, c0)) f
//let cSucc2 cn = fun f -> f << (cn f)
// Add, Multiply and Subtract church numerals
let cAdd cn cm = fun f -> cn f << cm f
let cMult cn cm = cn >> cm
let cSub cn cm = cm cPred cn
//Basic function for checking validity of numeral operations
let f = (fun x -> x + 1)
//This works
(cPred << cPred) c3 f 0
//This doesn't
c2 cPred c3 f 0
This is the type mismatch error given (Intellisense says this is an error with cPred on the last line of the code). I can see the output type is inferred wrong. Is there a way to fix it or is there something fundamentally wrong with how I have written this implementation?
'((bool * (('a -> 'a) -> 'a -> 'a) -> bool * (('a -> 'a) -> 'a -> 'a)) -> bool * (('a -> 'a) -> 'a -> 'a) -> bool * (('a -> 'a) -> 'a -> 'a)) -> (bool * (('a -> 'a) -> 'a -> 'a) -> bool * (('a -> 'a) -> 'a -> 'a)) -> bool * (('a -> 'a) -> 'a -> 'a) -> bool * (('a -> 'a) -> 'a -> 'a)'
but given a
'((bool * (('a -> 'a) -> 'a -> 'a) -> bool * (('a -> 'a) -> 'a -> 'a)) -> bool * (('a -> 'a) -> 'a -> 'a) -> bool * (('a -> 'a) -> 'a -> 'a)) -> ('a -> 'a) -> 'a -> 'a'
The types ''a' and 'bool * (('a -> 'a) -> 'a -> 'a)' cannot be unified.
In the below explanation I will assume a definition of type CN<'a> = ('a -> 'a) -> 'a -> 'a (where "CN" stands for "Church Numeral") in order to shorten the explanation and reduce clutter.
Your attempted application of c2 to cPred fails, because c2 expects an argument of type 'a -> 'a, but cPred is not such function.
You may expect cPred to match the expected type, because you have declared it as CN<'a> -> CN<'a>, but that is not the true type. Because you are applying argument cn to type bool*CN<'a> -> bool*CN<'a> (which is the type of cSucc), the compiler infers that cn must have type of CN<bool*CN<'a>>, and therefore cPred gets the type of CN<bool*CN<'a>> -> CN<'a>, which does not match what c2 expects.
All of this comes down to this fact: functions lose their genericity when you pass them around as values.
Consider a simpler example:
let f (g: 'a -> 'a list) = g 1, g "a"
Such definition will not compile, because 'a is a parameter of f, not a parameter of g. Therefore, for a given execution of f, a specific 'a must be chosen, and it cannot be both int and string at the same time, and therefore, g cannot be applied to both 1 and "a".
Similarly, cn in cPred gets fixed to type bool*CN<'a> -> bool*CN<'a>, thus making the type of cPred itself incompatible with CN<_>.
In simple cases, there is an obvious workaround: pass g twice.
let f g1 g2 = g1 1, g2 "a"
let g x = [x]
f g g
// > it : int list * string list = [1], ["a"]
This way, g will lose genericity both times, but it will be specialized to different types - the first instance to int -> int list, the second - to string -> string list.
However, this is only a half-measure, suitable for the simplest cases only. A general solution will require the compiler to understand that we want 'a to be a parameter of g, not a parameter of f (this is usually referred to as "higher-rank type"). In Haskell (more specifically, GHC), there is a straightforward way to do this, with the RankNTypes extension enabled:
f (g :: forall a. a -> [a]) = (g 1, g "a")
g x = [x]
f g
==> ([1], ["a"])
Here, I explicitly tell the compiler that the parameter g has its own generic parameter a by including forall a in its type declaration.
F# does not have such explicit support for this, but it does offer a different feature that can be used to accomplish the same result - interfaces. Interfaces may have generic methods, and these methods do not lose genericity when interface instances are passed around. So we can reformulate the above simple example like this:
type G =
abstract apply : 'a -> 'a list
let f (g: G) = g.apply 1, g.apply "a"
let g = { new G with override this.apply x = [x] }
f g
// it : int list * string list = ([1], ["a"])
Yes, the syntax for declaring such "higher-rank functions" is heavy, but that's all F# has to offer.
So, applying this to your original problem, we need to declare CN as an interface:
type CN =
abstract ap : ('a -> 'a) -> 'a -> 'a
Then we can construct some numbers:
let c0 = { new CN with override __.ap f x = x }
let c1 = { new CN with override __.ap f x = f x }
let c2 = { new CN with override __.ap f x = f (f x) }
let c3 = { new CN with override __.ap f x = f (f (f x)) }
let c4 = { new CN with override __.ap f x = f (f (f (f x))) }
Then cSucc and cPred:
let cSucc (b,(cn:CN)) =
if b
then (b, { new CN with override __.ap f x = f (cn.ap f x) })
else (true, cn)
let cPred (cn:CN) = snd (cn.ap cSucc (false, c0))
Note that cPred now has inferred type of CN -> CN, exactly what we need.
Arithmetic functions:
let cAdd (cn: CN) (cm: CN) = { new CN with override __.ap f x = cn.ap f (cm.ap f x) }
let cMult (cn: CN) (cm: CN) = { new CN with override __.ap f x = cn.ap cm.ap f x }
let cSub (cn: CN) (cm: CN) = cm.ap cPred cn
Note, all of them get the inferred type of CN -> CN -> CN, as expected.
And finally, your examples:
let f = (fun x -> x + 1)
//This works
((cPred << cPred) c3).ap f 0
//This also works now
(c2.ap cPred c3).ap f 0

F#, concise way to define map4 using map2 and map3

This question is for amusement only. Please don't take this question too seriously.
I am currently learning F#, and I am interested to see if there is a concise way to define map4, using existing functions List.map2, List.map3, pipe forward/backward, forward/backward composition, etc.
i.e.
let map4 f a b c d = ......
map4 f [a1;a2] [b1;b2] [c1;c2] [d1;d2]
// output: [f(a1,b1,c1,d1); f(a2,b2,c2,d2)]
I can solve this recursively, or by defining a new operator (see the following URL)
http://www.fssnip.net/9W/title/nary-Seqmap-
http://call-with-cc-en.blogspot.sg/2009/04/applicative-functors-mapping-function.html
I can also solve this by combining List.map2 and List.map3, using partially applied functions f(a,b,?,?)
let map4 f a b c d =
List.map3 (fun g y -> g y) (List.map2 f a b) c d
I can try to shorten my code above using forward composition (and make it as abstract/confusing as possible)
let map4 f a =
List.map2 f a >> List.map3 id;;
// Output type: f:('a -> 'b -> 'c -> 'd -> 'e) ->
// a:'a list -> ('b list -> 'c list -> 'd list -> 'e list)
I would like to know if I can shorten it even further by getting rid of the "f" and "a", resulting in:
let map4 = ...... (* Use only List.map2, List.map3, |>, |<, >>, <<, etc.*) ..........
It will probably make it unnecessarily confusing, but it will be pretty cool. Thank you.
EDIT:
Adapting TheInnerLight's answer:
let inline (<!>) f xList = List.map f xList
let inline (<*>) gList xList = List.map2 (id) gList xList
let map4 f w x y z = f <!> w <*> x <*> y <*> z
let map5 f v w x y z = f <!> v <*> w <*> x <*> y <*> z
let map6 f u v w x y z = f <!> u <*> v <*> w <*> x <*> y <*> z
This is a good use for the applicative style of programming, i.e. using applicative functors.
Just define the apply function and some helper operators:
module List =
// val apply : f:('a -> 'b) list -> x:'a list -> 'b list
let apply f x = List.map2 (fun f x -> f x) f x
// val inline ( <!> ) : f:('a -> 'b) -> x:'a list -> 'b list
let inline (<!>) f x = List.map f x
// val inline ( <*> ) : f:('a -> 'b) list -> x:'a list -> 'b list
let inline (<*>) f x = apply f x
Then use map and apply to define mapN functions.
// val map2 : f:('a -> 'b -> 'c) -> x:'a list -> y:'b list -> 'c list
let map2 f x y = f <!> x <*> y
// val map3 : f:('a -> 'b -> 'c -> 'd) -> x:'a list -> y:'b list -> z:'c list -> 'd list
let map3 f x y z = f <!> x <*> y <*> z
// val map4 : f:('a -> 'b -> 'c -> 'd -> 'e) -> x:'a list -> y:'b list -> z:'c list -> a:'d list -> 'e list
let map4 f x y z a = f <!> x <*> y <*> z <*> a
// val map8 : f:('a -> 'b -> 'c -> 'd -> 'e -> 'f -> 'g -> 'h -> 'i) -> x:'a list -> y:'b list -> z:'c list -> a:'d list -> b:'e list -> c:'f list -> d:'g list -> e:'h list -> 'i list
let map8 f x y z a b c d e = f <!> x <*> y <*> z <*> a <*> b <*> c <*> d <*> e
As you can see, you can keep adding arguments to define arbitrary mapNs to your heart's content.
Since the question specifically asks about using map2 or map3, you can do this in the same style although it's a little less concise, e.g:
let map4_2 f x y z a = List.map2 f x y <*> z <*> a
let map4_3 f x y z a = List.map3 f x y z <*> a
Hopefully you get the idea.
As a small aside, I think it's worth noting that any monad is automatically an applicative functor, so there is a wide array of types you could use this pattern with, here is an Async example.
module Async =
// val map : f:('a -> 'b) -> x:Async<'a> -> Async<'b>
let map f x = async.Bind(x, async.Return << f)
// val apply : f:Async<('a -> 'b)> -> x:Async<'a> -> Async<'b>
let apply f x = async.Bind(f, fun fe -> map fe x)
// val inline ( <!> ) : f:('a -> 'b) -> x:Async<'a> -> Async<'b>
let inline (<!>) f x = map f x
// val inline ( <*> ) : f:Async<('a -> 'b)> -> x:Async<'a> -> Async<'b>
let inline (<*>) f x = apply f x
// val map4 : f:('a -> 'b -> 'c -> 'd -> 'e) -> x:Async<'a> -> y:Async<'b> -> z:Async<'c> -> a:Async<'d> -> Async<'e>
let map4 f x y z a = f <!> x <*> y <*> z <*> a
After lots of experimenting, I come up with the following "point-free" style answer:
// Warning: still have "Value Restriction" error
let map4 = List.map2 >> (>>) >> (|>) ((>>) >> (|>) (List.map3 id))
Unfortunately, the F# compiler will produce a "Value restriction" error, see:
https://blogs.msdn.microsoft.com/mulambda/2010/05/01/finer-points-of-f-value-restriction/
And so, I will settle with:
let map4 f =
f
|> ( List.map2 >> (>>) >> (|>) ((>>) >> (|>) (List.map3 id)) )
// val map4: f:('a->'b->'c->'d->'e) -> ('a list -> 'b list -> 'c list -> 'd list -> 'e list)

f# interface with type constraint infinite when unifying

I'm having problems getting an interface with type constraints to work generically.
Here's the type
type LeftistHeap<'a when 'a : comparison> =
...
interface IHeap<LeftistHeap<'a>, 'a> with
...
member this.Insert (x : 'a) = LeftistHeap.insert x this
and the interface
type IHeap<'a when 'a : comparison> =
inherit System.Collections.IEnumerable
inherit System.Collections.Generic.IEnumerable<'a>
...
type IHeap<'c, 'a when 'c :> IHeap<'c, 'a> and 'a : comparison> =
inherit IHeap<'a>
...
abstract member Insert : 'a -> 'c
this code works no problem
let insertThruList l h =
List.fold (fun (h' : LeftistHeap<'a>) x -> h'.Insert x ) h l
but if I try to genralize the code for the interface
let insertThruList l h =
List.fold (fun (h' : IHeap<_,'a>) x -> h'.Insert x ) h l
I get this error at h'.Insert
Type mismatch. Expecting a
'b
but given a
IHeap<'b,'a>
The resulting type would be infinite when unifying ''b' and 'IHeap<'b,'a>'
The compiler's right: you're trying to use a 'c where you need an IHeap<'c,_>. Since 'c :> IHeap<'c,_>, one solution is just to insert an upcast:
let insertThruList l h =
List.fold (fun (h' : IHeap<_,_>) x -> h'.Insert x :> _) h l
Alternatively, you can indicate that you don't want the input to be (exactly) an IHeap<_,_>, but instead some particular subtype:
let insertThruList l h =
List.fold (fun (h' : #IHeap<_,_>) x -> h'.Insert x) h l
This is probably what you really want (the type is more specific). This is equivalent to the more verbose definition:
let insertThruList<'c,'a when 'a : comparison and 'c :> IHeap<'c,'a>> l h =
List.fold (fun (h' : 'c) x -> h'.Insert x) h l
will this work for your case?
let insertThruList l (h : 'T when 'T :> IHeap<'T, 'a> ) =
List.fold (fun (h' : 'T) x -> h'.Insert x ) h l

Tupled function composition

I'm curious why this
let f = (fun a b -> a, b) >> obj.Equals
gives the error
No accessible member or object constructor named 'Equals' takes 1 arguments
but this works
let f = (fun a -> a, a) >> obj.Equals
Without defining a new combinator operator:
let f = (fun a b -> a, b) >> (<<) obj.Equals
>> (<<) is a nice trick, and can also be extended for more arguments:
let compose3 f g = f >> (<<) ((<<) g)
val compose3 : ('a -> 'b -> 'c -> 'd) -> ('d -> 'e) -> ('a -> 'b -> 'c -> 'e)
Consider the types. (>>) has type ('a -> 'b) ->('b -> 'c) -> ('a -> 'c), but you're trying to call it with arguments of type 'a -> ('b -> 'a*'b) and obj * obj -> bool, which can't be made to fit together like that.
You could of course define a new combinator for composing binary and unary functions:
let ( >>* ) f g a b = f a b |> g
in which case you can use it in your example instead of (>>).

Resources