I am currently having some trouble elegantly handling nested record lists.
lets say we have the types:
type BoxEntry = {
flag : bool
}
type Box = {
entries : BoxEntry list
}
type Entry = {
boxes : Box list
}
type Model = {
recEntries : Entry list
}
Now lets say I want to set a specific boxentry bool I have the list indexes of Entry, Box and BoxEntry however I have only found this approach to work for me:
let handleUnsetEntry (model : Model) (idxs : string* int * int) =
let(sendId, bi, ej) = idxs
let nEntry =
model.entries
|> List.map(fun x ->
if x.sendId = sendId then
{x with boxes =
x.boxes |> List.mapi (fun i y ->
if i = bi then
{y with boxEntry =
y.boxEntry |> List.mapi (fun j z ->
if j = ej then
z.SetFlag
else
z)}
else
y)}
else
x)
{model with entries = nEntry}, Cmd.none
This is obviously a really silly solution both efficiency-wise as well as readability-wise. Is there another approach to this which is more elegant I feel like there surely must be but I am not getting it.
Any help would be appreciated.
In FP there's a pattern called Lens or Prism. It's kind of composable functional attributes to simplify handling of nested immutable structures.
Lenses/Prisms allows you to zoom in on a nested attribute and get/set it while preserving immutability (set returns a new object).
Lenses/Prisms doesn't really answer what to do IIRC with structures that contains lists but if we ignore that and "hack something" we could end up with something like this:
type Prism<'O, 'I> = P of ('O -> 'I option)*('O -> 'I -> 'O)
That is, a prism consists of two functions; a getter and a setter. The getter given an outer value returns the inner value if it exists. The setter creates a new outer value given a new inner value.
This allows us too define the commonly used fstL and sndL prisms that allows zooming on the first respectively the second part of a pair.
let fstL =
let g o = o |> fst |> Some
let s (_, s) i = (i, s)
P (g, s)
let sndL =
let g o = o |> snd |> Some
let s (f, _) i = (f, i)
P (g, s)
We also define a way to combine two prisms
// Combines two prisms into one
let combineL (P (lg, ls)) (P (rg, rs)) =
let g o =
match lg o with
| None -> None
| Some io -> rg io
let s o i =
match lg o with
| None -> o
| Some io -> ls o (rs io i)
P (g, s)
let (>->) l r = combine l r
Using this we can define a prism that allows zooming into a rather complex structure:
let l = sndL >-> sndL >-> fstL
let o = (1, (2, (3, 4)))
get l o |> printfn "%A" //Prints 3
let o = set l o 33
get l o |> printfn "%A" //Prints 33
Given the Model given by OP we extend it with Prisms static attributes
type BoxEntry =
{
flag : bool
}
member x.SetFlag = {x with flag = true}
// Prisms requires some boiler plate code, this could be generated
static member flagL =
let g (o : BoxEntry) = Some o.flag
let s (o : BoxEntry) i = { o with flag = i }
P (g, s)
Putting it all together we can rewrite the handle function to something like this:
let handleUnsetEntry (model : Model) (idxs : string* int * int) =
let (sendId, bi, ej) = idxs
// Builds a Prism to the nested flag
let nestedFlagL =
Model.entriesL
>-> Prism.listElementL (fun _ (e : Entry) -> e.sendId) sendId
>-> Entry.boxesL
>-> Prism.listElementAtL bi
>-> Box.boxEntryL
>-> Prism.listElementAtL ej
>-> BoxEntry.flagL
Prism.set nestedFlagL model true
Hope this gave OP some ideas on how one can handle nested immutable structures.
The full source code:
// A Prism is a composable optionally available property
// It consist of a getter function that given an outer object returns
// the inner object if it's there
// Also a setter function that allows setting the inner object
// (if there's a feasible place)
// In FP there are patterns called Lens and Prisms, this is kind of a bastard Prism
type Prism<'O, 'I> = P of ('O -> 'I option)*('O -> 'I -> 'O)
module Prism =
let get (P (g, _)) o = g o
let set (P (_, s)) o i = s o i
let fstL =
let g o = o |> fst |> Some
let s (_, s) i = (i, s)
P (g, s)
let sndL =
let g o = o |> snd |> Some
let s (f, _) i = (f, i)
P (g, s)
// Combines two prisms into one
let combineL (P (lg, ls)) (P (rg, rs)) =
let g o =
match lg o with
| None -> None
| Some io -> rg io
let s o i =
match lg o with
| None -> o
| Some io -> ls o (rs io i)
P (g, s)
// Creates a Prism for accessing a listElement
let listElementL sel k =
let g o =
o
|> List.mapi (fun i v -> (sel i v), v)
|> List.tryPick (fun (kk, vv) -> if k = kk then Some vv else None)
let s o i =
o
|> List.mapi (fun i v -> (sel i v), v)
|> List.map (fun (kk, vv) -> if k = kk then i else vv)
P (g, s)
let listElementAtL i =
listElementL (fun j _ -> j) i
type Prism<'O, 'I> with
static member (>->) (l, r) = Prism.combineL l r
// Modified model to match the code in OPs post
type BoxEntry =
{
flag : bool
}
member x.SetFlag = {x with flag = true}
// Prisms requires some boiler plate code, this could be generated
static member flagL =
let g (o : BoxEntry) = Some o.flag
let s (o : BoxEntry) i = { o with flag = i }
P (g, s)
type Box =
{
boxEntry : BoxEntry list
}
static member boxEntryL =
let g (o : Box) = Some o.boxEntry
let s (o : Box) i = { o with boxEntry = i }
P (g, s)
type Entry =
{
sendId : string
boxes : Box list
}
static member sendIdL =
let g (o : Entry) = Some o.sendId
let s (o : Entry) i = { o with sendId = i }
P (g, s)
static member boxesL =
let g (o : Entry) = Some o.boxes
let s (o : Entry) i = { o with boxes = i }
P (g, s)
type Model =
{
entries : Entry list
}
static member entriesL =
let g (o : Model) = Some o.entries
let s (o : Model) i = { o with entries = i }
P (g, s)
let handleUnsetEntry (model : Model) (idxs : string* int * int) =
let (sendId, bi, ej) = idxs
// Builds a Prism to the nested flag
let nestedFlagL =
Model.entriesL
>-> Prism.listElementL (fun _ (e : Entry) -> e.sendId) sendId
>-> Entry.boxesL
>-> Prism.listElementAtL bi
>-> Box.boxEntryL
>-> Prism.listElementAtL ej
>-> BoxEntry.flagL
Prism.set nestedFlagL model true
[<EntryPoint>]
let main argv =
let model : Model =
{
entries =
[
{
sendId = "123"
boxes =
[
{
boxEntry =
[
{
flag = false
}
{
flag = false
}
]
}
]
}
]
}
printfn "Before change"
printfn "%A" model
let model = handleUnsetEntry model ("123", 0, 0)
printfn "After 1st change"
printfn "%A" model
let model = handleUnsetEntry model ("123", 0, 1)
printfn "After 2nd change"
printfn "%A" model
let model = handleUnsetEntry model ("Hello?", 0, 1)
printfn "After missed change"
printfn "%A" model
0
Related
My old notes on ML say that
let (๐ฃโ, โฆ , ๐ฃโ) = (๐กโ, โฆ , ๐กโ) in ๐กโฒ
is a syntactic sugar for
(ฮป ๐ฃโ. โฆ (ฮป ๐ฃโ. ๐กโฒ)๐กโ โฆ )๐กโ
and that
let (๐ฃโ, ๐ฃโ) = ๐ก ๐กโฒ in ๐กโณ
is equivalent to
let ๐ฃ = ๐ก ๐กโฒ in
let ๐ฃโ = snd ๐ฃ in
let ๐ฃโ = fst ๐ฃ in
๐กโณ
where
each ๐ฃ (with or without a subscript) stands for a variable,
each ๐ก (with or without a sub- or a superscript) stands for a term, and
fst and snd deliver the first and second component of a pair, respectively.
I'm wondering whether I got the evaluation order right because I didn't note the original reference. Could anyone ((confirm or reject) and (supply a reference))?
It shouldn't matter whether it's:
let ๐ฃ = ๐ก ๐กโฒ in
let ๐ฃโ = snd ๐ฃ in
let ๐ฃโ = fst ๐ฃ in
๐กโณ
Or:
let ๐ฃ = ๐ก ๐กโฒ in
let ๐ฃโ = fst ๐ฃ in
let ๐ฃโ = snd ๐ฃ in
๐กโณ
Since neither fst nor snd have any side-effects. Side-effects may exist in the evaluation of ๐ก ๐กโฒ but that's done before the let binding takes place.
Additionally, as in:
let (๐ฃโ, ๐ฃโ) = ๐ก ๐กโฒ in ๐กโณ
Neither ๐ฃโ nor ๐ฃโ is reliant on the value bound to the other to determine its value, so the order in which they're bound is again seemingly irrelevant.
All of that said, there may be an authoritative answer from those with deeper knowledge of the SML standard or the inner workings of OCaml's implementation. I simply am uncertain of how knowing it will provide any practical benefit.
Practical test
As a practical test, running some code where we bind a tuple of multiple expressions with side-effects to observe order of evaluation. In OCaml (5.0.0) the order of evaluation is observed to be right-to-left. We observe tthe same when it comes to evaluating the contents of a list where those expressions have side-effects as well.
# let f () = print_endline "f"; 1 in
let g () = print_endline "g"; 2 in
let h () = print_endline "h"; 3 in
let (a, b, c) = (f (), g (), h ()) in a + b + c;;
h
g
f
- : int = 6
# let f () = print_endline "f"; 1 in
let g () = print_endline "g"; 2 in
let h () = print_endline "h"; 3 in
let (c, b, a) = (h (), g(), f ()) in a + b + c;;
f
g
h
- : int = 6
# let f _ = print_endline "f"; 1 in
let g () = print_endline "g"; 2 in
let h () = print_endline "h"; 3 in
let a () = print_endline "a" in
let b () = print_endline "b" in
let (c, d, e) = (f [a (); b ()], g (), h ()) in
c + d + e;;
h
g
b
a
f
- : int = 6
In SML (SML/NJ v110.99.3) we observe the opposite: left-to-right evaluation of expressions.
- let
= fun f() = (print "f\n"; 1)
= fun g() = (print "g\n"; 2)
= fun h() = (print "h\n"; 3)
= val (a, b, c) = (f(), g(), h())
= in
= a + b + c
= end;
f
g
h
val it = 6 : int
- let
= fun f() = (print "f\n"; 1)
= fun g() = (print "g\n"; 2)
= fun h() = (print "h\n"; 3)
= val (c, b, a) = (h(), g(), f())
= in
= a + b + c
= end;
h
g
f
val it = 6 : int
- let
= fun f _ = (print "f\n"; 1)
= fun g() = (print "g\n"; 2)
= fun h() = (print "h\n"; 3)
= fun a() = print "a\n"
= fun b() = print "b\n"
= val (c, d, e) = (f [a(), b()], g(), h())
= in
= c + d + e
= end;
a
b
f
g
h
val it = 6 : int
Be aware that, in OCaml, due to the (relaxation of the) value restriction, let a = b in c is not equivalent to (fun a -> c)b. A counterexample is
# let id = fun x -> x in id 5, id 'a';;
- : int * char = (5, 'a')
# (fun id -> id 5, id 'a')(fun x -> x)
Error: This expression has type char but an expression was expected of type int
#
This means that they are semantically not the same construction (the let ... = ... in ... is strictly more general that the other).
This happens because, in general, the type system of OCaml doesn't allow types of the form (โฮฑ.ฮฑโฮฑ) โ int * char (because allowing them would make typing undecidable, which is not very practical), which would be the type of fun id -> id 5, id 'a'. Instead, it resorts to having the less general type โฮฑ.(ฮฑโฮฑ) โ ฮฑ * ฮฑ, which doesn't make it typecheck, because you can't unify both ฮฑ with char and with int.
This question already has answers here:
transpose of a list of lists
(3 answers)
Closed 12 months ago.
I'd like to write a function in OCaml, using only recursivity that can transform any list of list that look like: [[a1;...;an];[b1;...bn];...;[z1;...;zn]] into [[a1;b1;...;z1];...;[an;...;zn]] what I've done so far is quite complex, I insert element by element reconstructing a new list every time ... and I'm sure there is a simpler way ...
My code so far:
let inserer l e i =
let rec aux l e i j =
match l with
| [] -> failwith "erreur position inexistante"
| t::q when j = i ->
if List.length t = 0 then
[e]::q
else
let t1 = List.hd t in
let q1 = List.tl t in
let l1 = t1::e::q1 in
l1::q
| t::q -> t::(aux q e i (j+1))
in
aux l e i 0
let inserer_liste b m =
let rec aux b m i =
match b with
| [] -> m
| t::q ->
let tmp = inserer m t i in
aux q tmp (i+1)
in
aux b m 0
let transform u n =
let rec aux u m =
match u with
| []-> m
| b::q ->
let tmp = inserer_liste b m in
aux q tmp
in
aux u (List.init n (fun _ -> []))
let u = [[1;2;3]; [4;5;6]; [7;8;9]]
let l = transform u 3
I have a feeling that this transformation is way more natural if you transform an array of lists into a lists of arrays. You can transform into a list of lists afterwards.
let rec f a =
match a.(0) with
| [] -> []
| _ :: _ ->
let hd = Array.map List.hd a in
for i = 0 to Array.length a - 1 do
a.(i) <- List.tl a.(i)
done ;
hd :: (f a)
This consumes the input array, which can be solved by shadowing f in the following way :
let f a = f (Array.copy a)
let f_list l = List.map Array.to_list (f (Array.of_list l))
You could also reallocate a new array at each recursive call, but that would be slower, without any upside except maybe a bit nicer code.
f_list is more elegant this way :
let f_list l =
l |> Array.of_list |> f |> List.map Array.to_list
There is no error handling in my code : it assumes all list have the same length, but it should be to hard to add it.
Is there a simple way... Not that I know of but that doesn't say much.
Here's something I tried.
let lol =
[
[ 1; 2; 3; 4; ];
[ 5; 6; 7; 8; ];
[ 9; 10; 11; 12; ];
]
let ans =
List.fold_left
(
fun a e ->
match a with
| [] -> List.fold_right (fun e a -> [e]::a) e a
| _ -> List.fold_right2 (fun b c acc -> (c # [b])::acc) e a []
)
[]
lol
let () =
List.iter
(
fun l ->
List.iter (fun x -> Printf.printf "%d " x) l;
print_newline()
)
ans
After some thought I cam up with this
let lol =
[
[11; 12; 13; 14; 15; 16; 17; 18; 19; ];
[21; 22; 23; 24; 25; 26; 27; 28; 29; ];
[31; 32; 33; 34; 35; 36; 37; 38; 39; ];
[41; 42; 43; 44; 45; 46; 47; 48; 49; ];
]
let rec transpose ll =
match ll with
| [] -> []
| l -> (List.map List.hd l)::
(
try
transpose (List.map List.tl l)
with
| _ -> []
)
let ans = transpose lol
let () =
List.iter
(
fun l -> List.iter (fun x -> Printf.printf "%d " x) l; print_newline()
)
ans
Nested F# Record with generic type parameter, how do I statically cast between types in nested structure equivalent to traversing and performing 'T |> 'K, e.g. float |> int?
Currently I am Naively traversing the nested records and explicitly converting the type with from:float |> to:int or equivalently int(from). However, this is not very beautiful.
type Person<'T> = {Id : int; Value : 'T}
type Family<'T> = {Id : 'T; People : seq<Person<'T>>}
let fam1 = {Id = 1.0; People = [{Id = 1.1; Value = 2.9}; {Id = 1.2; Value = 4.4}]} : Family<float>
let fam2 = {Id = 2.0; People = [{Id = 2.1; Value = 3.9}; {Id = 2.2; Value = 5.4}]} : Family<float>
let partyFloat = seq{ yield fam1; yield fam2}
// In general, how to do this from a type T to a type K where conversion using T |> K will work
let partyInt : seq<Family<int>> = partyFloat
How to statically and/or
lazily convert to seq<Family<int>>?
In my real world case I have a DiffSharp D type that can be converted to a float with D |> float or float(D).
There is no magic way to cast the insides of types, you have to write your own.
It is idiomatic for F# and functional programming in general (and I personally recommend it, too) to write small functions for simple data transformations, and then assemble them together:
let mapPerson f p = { Id = p.Id; Value = f p.Value }
let mapFamily f fm = { Id = f fm.Id; People = Seq.map (mapPerson f) fm.People }
let mapParty f = Seq.map (mapFamily f)
let partyInt = mapParty int partyFloat
But of course you can do it in one big messy go:
let partyInt =
partyFloat
|> Seq.map (fun fm ->
{ Id = int fm.Id
People =
fm.People
|> Seq.map (fun p ->
{ Id = p.Id; Value = int p.Value }
)
}
)
It seems like what you are asking for are covariance ie that this should compile
let vs : obj list = ["1"; "2"]
F# doesn't support covariance (or contravariance) and probably never will. C# does however so you could write something like this
using System.Collections.Generic;
interface IPerson<out T>
{
int Id { get; }
T Value { get; }
}
interface IFamily<out T>
{
int Id { get; }
IEnumerable<IPerson<T>> Members { get; }
}
static class Program
{
static IFamily<string> CreateFamily()
{
return null;
}
static void Main(string[] args)
{
IFamily<string> familyOfString = CreateFamily();
IFamily<object> familyOfObject = familyOfString;
}
}
However, there's a functional pattern that could help us called polymorphic lenses.
(Picture from reddit thread: https://www.reddit.com/r/haskell/comments/2qjnho/learning_curves_for_different_programming/)
I used to think that polymorphic lenses isn't possible in F# due to the lack of higher-rank types. However, there's a hidden gem out there: http://www.fssnip.net/7Pk
Vesa Karvonen (IIRC he is also behind hopac so he's pretty cool) implements polymorphic lenses in F# using some pretty interesting tricks.
We can then map the inner values of an immutable structure reasonably easy.
let input : Family<int> =
{
Id = 1
Members = [{ Id = 10; Value = 123}; { Id = 11; Value = 456}]
}
printfn "%A" input
let output : Family<string> =
input
|> over Family.membersL (overAll Person.valueL ((+) 1 >> string))
printfn "%A" output
Full source code
// ----------------------------------------------------------------------------
// The code below taken from: http://www.fssnip.net/7Pk
// by Vesa+Karvonen - http://www.fssnip.net/authors/Vesa+Karvonen
// ----------------------------------------------------------------------------
type LensFunctor<'a> =
| Over of 'a
| View
member t.map a2b =
match t with
| Over a -> Over (a2b a)
| View -> View
type Lens<'s,'t,'a,'b> = ('a -> LensFunctor<'b>) -> 's -> LensFunctor<'t>
module Lens =
let view l s =
let r = ref Unchecked.defaultof<_>
s |> l (fun a -> r := a; View) |> ignore
!r
let over l f =
l (f >> Over) >> function Over t -> t | _ -> failwith "Impossible"
let set l b = over l <| fun _ -> b
let (>->) a b = a << b
let lens get set = fun f s ->
(get s |> f : LensFunctor<_>).map (fun f -> set f s)
let fstL f = lens fst (fun x (_, y) -> (x, y)) f
let sndL f = lens snd (fun y (x, _) -> (x, y)) f
// ----------------------------------------------------------------------------
// The code above taken from: http://www.fssnip.net/7Pk
// by Vesa+Karvonen - http://www.fssnip.net/authors/Vesa+Karvonen
// ----------------------------------------------------------------------------
let overAll l f = List.map (over l f)
open Lens
type Person<'T> = { Id : int; Value : 'T }
module Person =
let idS i p = { p with Id = i }
let valueS v { Id = i } = { Id = i; Value = v }
let idL f = lens (fun {Id = i } -> i) idS f
let valueL f = lens (fun {Value = v } -> v) valueS f
type Family<'T> = { Id : int; Members : Person<'T> list }
module Family =
let idS i f = { f with Id = i }
let membersS m { Id = i } = { Id = i; Members = m }
let idL f = lens (fun {Id = i } -> i) idS f
let membersL f = lens (fun {Members = m } -> m) membersS f
[<EntryPoint>]
let main argv =
let input =
{
Id = 1
Members = [{ Id = 10; Value = 123}; { Id = 11; Value = 456}]
}
printfn "%A" input
let output =
input
|> over Family.membersL (overAll Person.valueL ((+) 1 >> string))
printfn "%A" output
0
I want to write a function that gives the cartesiant product of two sequences that's what i did but i thought that it can be interesting to have less complexity with I want to browsing once the first sequence s1 and n times the second using map and then append all the results:
`let cartesian_product a b =
let na = length a in
let nb = length b in
init
(na * nb)
(fun j -> let i = j / nb in
at a i, at b (j - i*nb))
`
that's what i did for the moment :
`let rec cartesian_product a b =
let rec aux x b () = match b () with
| Nil -> Nil
| Cons(e, b) -> Cons ((x, e), aux x b)
in
match a () with
| Nil -> nil
| Cons (x, a) -> append (aux x b) (cartesian_product a b)`
but i didn't use map (is there a better way for doing that)??
Your aux function is essentially a specific case of map so you can write:
let rec cartesian_product a b = match a () with
| Nil -> Nil
| Cons (x, a) -> append (map (fun e -> (x, e)) b) (cartesian_product a b)
As a rule of thumb when you feel the need to write a function called aux, take a step back and think whether you can use map or fold. In fact, you could improve my code by using a fold instead of deconstructing the sequence yourself.
Here an example of the algorithm with a structure of list :
let cartesian_product a b =
let open List in
let mk_tuple l n = map (fun x -> (n,x)) l in
a |> map (mk_tuple b) |> fold_left append []
This will give you :
cartesian_product [0;1] [2;3];;
- : (int * int) list = [(0, 2); (0, 3); (1, 2); (1, 3)]
I have an OCaml code, and I have a hard time to formalize the function mi_pol into Coq because I am not understand clearly what exactly this code working, for example at the
aux (vec_add add const (vector ci v)) args ps
and
args.(i-1) <- mat_add add args.(i-1) (matrix ci m); aux const args ps
and
aux (vec_0 z dim) (Array.make n (mat_0 z dim)) ps
This is the code:
let vector = List.map;;
let clist x =
let rec aux k = if k <= 0 then [] else x :: aux (k-1) in aux;;
let vec_add add v1 v2 =
try List.map2 add v1 v2
with Invalid_argument _ ->
error_fmt "sum of two vectors of different size";;
let mat_add add m1 m2 =
try List.map2 (vec_add add) m1 m2
with Invalid_argument _ ->
error_fmt "sum of two matrices of different size";;
(*vector zero *)
let vec_0 z dim = clist z dim;;
(* matrix zero *)
let mat_0 z dim = clist (vec_0 z dim) dim;;
let comp f g x = f (g x);;
(* matrix transpose *)
let transpose ci =
let rec aux = function
| [] | [] :: _ -> []
| cs -> List.map (comp ci List.hd) cs :: aux (List.map List.tl cs)
in aux;;
(* matrix *)
let matrix ci m =
try transpose ci m
with Failure _ -> error_fmt "ill-formed matrix";;
let mi_pol z add ci =
let rec aux const args = function
| [] -> { mi_const = const; mi_args = Array.to_list args }
| Polynomial_sum qs :: ps -> aux const args (qs # ps)
| Polynomial_coefficient (Coefficient_matrix [v]) :: ps
| Polynomial_coefficient (Coefficient_vector v) :: ps ->
aux (vec_add add const (vector ci v)) args ps
| Polynomial_product [p] :: ps -> aux const args (p :: ps)
| Polynomial_product [Polynomial_coefficient (Coefficient_matrix m);
Polynomial_variable i] :: ps ->
args.(i-1) <- mat_add add args.(i-1) (matrix ci m);
aux const args ps
| _ -> not_supported "todo"
in fun dim n -> function
| Polynomial_sum ps -> aux (vec_0 z dim) (Array.make n (mat_0 z dim)) ps
| _ -> not_supported
"todo";;
Any help is very appreciate. If you can have a Coq code for mi_pol it will help me a lot.
It appears to take a polynomial on a vector space, and compute the sum of all the (transpose of) (matrix) coefficients attached to each variable. args is an array such that args.(i) is the sum of all coefficients on the i-th variable, and const the sum of constant scalars.
I don't know what's the meaning of this operation, but I suspect it doesn't mean much in the general case (working over arbitrary products of sums of products of ...; that would lead to strange non-linear/homogeneous behaviors). I suppose there are implicit constraints on what the shape of actual values of this polynomial type are, for example it may be linear in all variables.