I'm new to F# and have a question about functions pipeline. Let's say we have a function map which maps list of functions to array of values creating a list of arrays:
//val map : ('a -> 'b) list -> 'a [] -> 'b [] list
let map funcs vals =
funcs |> List.map (fun f -> Array.map f vals)
Usage example:
//val it : float [] list = [[|1.0; 1.144729886|]; [|15.15426224; 23.14069263|]]
map [log; exp] [|Math.E; Math.PI|]
Is there a way to replace lambda function (fun f -> Array.map f vals) with a chain of pipeline operators?
I'd like to write smth like:
//val map : 'a [] list -> ('a -> 'b) -> 'b [] list
let map funcs vals = funcs |> List.map (vals |> Array.map)
But this doesn't work.
Many thanks,
Ivan
You can use this one.
let map funcs vals = funcs |> List.map (Array.map >> ((|>) vals))
The part Array.map >> ((|>) vals) partially applies f to Array.map and then composes it with the application of vals.
To me, the most readable cross-product function would be:
let flip f y x = f x y // a pretty standard function for flipping arguments of function
let crossProduct funcs vals =
(<|)
>> flip Array.map vals
|> flip List.map funcs
let result = crossProduct [log; exp] [|Math.E; Math.PI|]
TL;DR: A bit of explanation.
The pattern: xs |> List.map f is very popular, but sometimes it is better to write:
f |> List.map <| xs
Or, using flip: f |> flip List.map xs
Considering this, let's write the function in the most straightforward way:
let cartesianProduct0 funcs vals =
fun f ->
fun v -> f v
|> (flip Array.map vals)
|> (flip List.map funcs)
Then you notice that fun v -> f v is actually (<):
fun f ->
((<|) f)
|> (flip Array.map vals)
or:
fun f ->
f
|> (<|)
|> (flip Array.map vals)
or, simply:
(<|)
>> flip Array.map vals
The rest you need to do is just a minor style refactoring.
Related
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.
I have a function that takes two lists and generates a Cartesian product.
let cartesian xs ys = xs |> List.collect (fun x -> ys |> List.map (fun y -> x * y))
My problem is I am passing two lists of type Int64, and I am getting errors because the function is expecting two lists of type Int32.
How does one explicitly set the list type?
Adding a type annotation to one of the arguments should work:
let cartesian (xs: int64 list) ys =
xs |> List.collect (fun x -> ys |> List.map (fun y -> x * y))
Alternatively, use inline to infer types at call site:
let inline cartesian xs ys =
xs |> List.collect (fun x -> ys |> List.map (fun y -> x * y))
> cartesian [1;2;3] [1;2;3];;
val it : int list = [1; 2; 3; 2; 4; 6; 3; 6; 9]
> cartesian [1L;2L;3L] [1L;2L;3L];;
val it : int64 list = [1L; 2L; 3L; 2L; 4L; 6L; 3L; 6L; 9L]
Extended comment: A third alternative exists, factoring out the part of the code which introduces the constraint. Because the F# multiplication operator has the signature
val inline ( * ) : ^T1 -> ^T2 -> ^T3
when (^T1 or ^T2) : (static member (*) : ^T1 * ^T2 -> ^T3)
its static member constraint cannot be generalized unless the code in which it appears is marked inline. Move the operator to the call site:
let cartesian f xs ys =
List.collect (fun x -> List.map (f x) ys) xs
// val cartesian : f:('a -> 'b -> 'c) -> xs:'a list -> ys:'b list -> 'c list
cartesian (*) [1L..3L] [1L..3L]
// val it : int64 list = [1L; 2L; 3L; 2L; 4L; 6L; 3L; 6L; 9L]
This is a reference question to this: StackOverflow in continuation monad
with whom I played a little and would need a few clarifications.
1) I suppose this:
member this.Delay(mk) = fun c -> mk () c
makes the behavior in computational workflow do the diffrence as showed by toyvo between these:
cBind (map xs) (fun xs -> cReturn (f x :: xs))
cBind (fun c -> map xs c) (fun xs -> cReturn (f x :: xs))
So I don't exactly understand what is the trick, when
(fun c -> map xs c) is only different notation of (map xs)
2) Inference issue. - In OP's second map example I found out it doesn't compile due to inference problem with v value, because it infers f as a -> b list, instead of desired a -> b. Why it infers in this way? In case let v = f x it would infer well.
3) It seems to me that VS shows inaccurate type signatures in the tooltips:
return type of the monad's Return is: ('e->'f)->f, while the return type of the Bind is only 'c->'b. -It seems it simplify ('e->'f) to only c in the Bind case, or am I missing something here?
Thanks for the clarification,
tomas
Edit - testing dump:
let cReturn x = fun k -> k x
let cBind m f =
printfn "cBind %A" <| m id
fun c -> m (fun a -> f a c)
let map_fixed f xs =
let rec map xs =
printfn "map %A" xs
match xs with
| [] -> cReturn []
| x :: xs -> cBind (fun c -> map xs c) (fun xs -> cReturn (f x :: xs))
map xs (fun x -> x)
let map f xs =
let rec map xs =
printfn "map %A" xs
match xs with
| [] -> cReturn []
| x :: xs -> cBind (map xs) (fun xs -> cReturn (f x :: xs))
map xs (fun x -> x)
[1..2] |> map_fixed ((+) 1) |> printfn "%A"
[1..2] |> map ((+) 1) |> printfn "%A"
map_fixed:
map [1; 2]
map [2]
map []
cBind []
map []
cBind [3]
map [2]
map []
cBind []
map []
[2; 3]
map:
map [1; 2]
map [2]
map []
cBind []
cBind [3]
[2; 3]
Edit to question 2:
let map f xs =
let rec map xs =
cont {
match xs with
| [] -> return []
| x :: xs ->
let v = f x // Inference ok
//let! v = cont { return f x } // ! Inference issue - question 2
let! xs = map xs
return v :: xs
}
map xs id
The issue is exactly that fun c -> map xs c is not the same as map xs. They have the same "meaning" in some sense, but their runtime semantics are different. In the latter case, evaluating the expression results in an immediate call to the map function with xs as an argument (returning another function as the result). On the other hand, evaluating fun c -> map xs c does not result in an immediate call to map! The call to map is delayed until the resulting function is actually applied. This is the critical difference that prevents a stack overflow.
Regarding your other questions, I can't quite make out what you're asking in your second question. For your third question, the compiler has inferred the most general type possible for Bind. You're right that the traditional type that you might expect is more specific than this, but it's not really a problem that you can call Bind in a wider set of contexts than is strictly necessary. And if you really want a more specific type, you can always add annotations to constrain the signature.
I should split seq<a> into seq<seq<a>> by an attribute of the elements. If this attribute equals by a given value it must be 'splitted' at that point. How can I do that in FSharp?
It should be nice to pass a 'function' to it that returns a bool if must be splitted at that item or no.
Sample:
Input sequence: seq: {1,2,3,4,1,5,6,7,1,9}
It should be splitted at every items when it equals 1, so the result should be:
seq
{
seq{1,2,3,4}
seq{1,5,6,7}
seq{1,9}
}
All you're really doing is grouping--creating a new group each time a value is encountered.
let splitBy f input =
let i = ref 0
input
|> Seq.map (fun x ->
if f x then incr i
!i, x)
|> Seq.groupBy fst
|> Seq.map (fun (_, b) -> Seq.map snd b)
Example
let items = seq [1;2;3;4;1;5;6;7;1;9]
items |> splitBy ((=) 1)
Again, shorter, with Stephen's nice improvements:
let splitBy f input =
let i = ref 0
input
|> Seq.groupBy (fun x ->
if f x then incr i
!i)
|> Seq.map snd
Unfortunately, writing functions that work with sequences (the seq<'T> type) is a bit difficult. They do not nicely work with functional concepts like pattern matching on lists. Instead, you have to use the GetEnumerator method and the resulting IEnumerator<'T> type. This often makes the code quite imperative. In this case, I'd write the following:
let splitUsing special (input:seq<_>) = seq {
use en = input.GetEnumerator()
let finished = ref false
let start = ref true
let rec taking () = seq {
if not (en.MoveNext()) then finished := true
elif en.Current = special then start := true
else
yield en.Current
yield! taking() }
yield taking()
while not (!finished) do
yield Seq.concat [ Seq.singleton special; taking()] }
I wouldn't recommend using the functional style (e.g. using Seq.skip and Seq.head), because this is quite inefficient - it creates a chain of sequences that take value from other sequence and just return it (so there is usually O(N^2) complexity).
Alternatively, you could write this using a computation builder for working with IEnumerator<'T>, but that's not standard. You can find it here, if you want to play with it.
The following is an impure implementation but yields immutable sequences lazily:
let unflatten f s = seq {
let buffer = ResizeArray()
let flush() = seq {
if buffer.Count > 0 then
yield Seq.readonly (buffer.ToArray())
buffer.Clear() }
for item in s do
if f item then yield! flush()
buffer.Add(item)
yield! flush() }
f is the function used to test whether an element should be a split point:
[1;2;3;4;1;5;6;7;1;9] |> unflatten (fun item -> item = 1)
Probably no the most efficient solution, but this works:
let takeAndSkipWhile f s = Seq.takeWhile f s, Seq.skipWhile f s
let takeAndSkipUntil f = takeAndSkipWhile (f >> not)
let rec splitOn f s =
if Seq.isEmpty s then
Seq.empty
else
let pre, post =
if f (Seq.head s) then
takeAndSkipUntil f (Seq.skip 1 s)
|> fun (a, b) ->
Seq.append [Seq.head s] a, b
else
takeAndSkipUntil f s
if Seq.isEmpty pre then
Seq.singleton post
else
Seq.append [pre] (splitOn f post)
splitOn ((=) 1) [1;2;3;4;1;5;6;7;1;9] // int list is compatible with seq<int>
The type of splitOn is ('a -> bool) -> seq<'a> -> seq>. I haven't tested it on many inputs, but it seems to work.
In case you are looking for something which actually works like split as an string split (i.e the item is not included on which the predicate returns true) the below is what I came up with.. tried to be as functional as possible :)
let fromEnum (input : 'a IEnumerator) =
seq {
while input.MoveNext() do
yield input.Current
}
let getMore (input : 'a IEnumerator) =
if input.MoveNext() = false then None
else Some ((input |> fromEnum) |> Seq.append [input.Current])
let splitBy (f : 'a -> bool) (input : 'a seq) =
use s = input.GetEnumerator()
let rec loop (acc : 'a seq seq) =
match s |> getMore with
| None -> acc
| Some x ->[x |> Seq.takeWhile (f >> not) |> Seq.toList |> List.toSeq]
|> Seq.append acc
|> loop
loop Seq.empty |> Seq.filter (Seq.isEmpty >> not)
seq [1;2;3;4;1;5;6;7;1;9;5;5;1]
|> splitBy ( (=) 1) |> printfn "%A"
if I have array A, and I have another bool array isChosen with the same length of A how can I build a new array from A where isChosen is true? something like A.[isChosen]? I cannot use Array.filter directly since isChosen is not a function of A elements and there is no Array.filteri like Array.mapi.
zip should help:
let l = [|1;2;3|]
let f = [|true; false; true|]
let r = [| for (v, f) in Seq.zip l f do if f then yield v|]
// or
let r = (l, f) ||> Seq.zip |> Seq.filter snd |> Seq.map fst |> Seq.toArray
Try the zip operator
seq.zip A isChosen
|> Seq.filter snd
|> Seq.map fst
|> Array.ofSeq
This will create a sequence of tuples where one value is from A and the other is from isChosen. This will pair the values together and make it very easy to filter them out in a Seq.filter expression
It's not as elegant or 'functional' as the other answers, but every once in a while I like a gentle reminder that you can use loops and array indices in F#:
let A = [|1;2;3|]
let isChosen = [|true; false; true|]
let r = [| for i in 0..A.Length-1 do
if isChosen.[i] then
yield A.[i] |]
printfn "%A" r
:)
And here are two more ways, just to demonstrate (even) more F# library functions:
let A = [|1;2;3|]
let isChosen = [|true;false;true|]
let B = Seq.map2 (fun x b -> if b then Some x else None) A isChosen
|> Seq.choose id
|> Seq.toArray
let C = Array.foldBack2 (fun x b acc -> if b then x::acc else acc) A isChosen []
|> List.toArray
My personal favorite for understandability (and therefore maintainability): desco's answer
let r = [| for (v, f) in Seq.zip l f do if f then yield v|]