caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] pattern matching on mapped lists
       [not found] <20150602100015.E87D67EEF7@sympa.inria.fr>
@ 2015-06-02 22:23 ` Nils Becker
  2015-06-03 16:52   ` Romain Bardou
  2015-06-03 16:58   ` John Whitington
  0 siblings, 2 replies; 5+ messages in thread
From: Nils Becker @ 2015-06-02 22:23 UTC (permalink / raw)
  To: caml-list

I find this syntax handy

    let [ii; jj] = List.map float_of_int [i; j] in
    ... do stuff with the floats

because it avoids repeating the function call. The compiler lets this
pass but warns that the matching is not exhaustive since [] is not
matched. This actually can't happen if I'm not mistaken. So, is this
considered good style, or is there a better idiomatic way to do multiple
assignments? If yes, should this be an enhancement request for the type
checker?

n.



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Caml-list] pattern matching on mapped lists
  2015-06-02 22:23 ` [Caml-list] pattern matching on mapped lists Nils Becker
@ 2015-06-03 16:52   ` Romain Bardou
  2015-06-03 17:42     ` Mikhail Mandrykin
  2015-06-03 16:58   ` John Whitington
  1 sibling, 1 reply; 5+ messages in thread
From: Romain Bardou @ 2015-06-03 16:52 UTC (permalink / raw)
  To: caml-list

On 03/06/2015 00:23, Nils Becker wrote:
> I find this syntax handy
>
>      let [ii; jj] = List.map float_of_int [i; j] in
>      ... do stuff with the floats
>
> because it avoids repeating the function call. The compiler lets this
> pass but warns that the matching is not exhaustive since [] is not
> matched. This actually can't happen if I'm not mistaken. So, is this
> considered good style, or is there a better idiomatic way to do multiple
> assignments? If yes, should this be an enhancement request for the type
> checker?
>
> n.

The type-checker cannot find out that List.map returns a list of the 
same size. I think it would require dependent types. Maybe some GADT can 
encode this, but it would be a bit messy.

If you use this idiom often, maybe you should define some map functions 
on tuples, whose length is known at compile-time:

let map2 f (x, y) = f x, f y

let (ii, jj) = map2 float_of_int (i, j) in
...

Unfortunately you need to define map2, map3, map4...

Cheers,

-- 
Romain

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Caml-list] pattern matching on mapped lists
  2015-06-02 22:23 ` [Caml-list] pattern matching on mapped lists Nils Becker
  2015-06-03 16:52   ` Romain Bardou
@ 2015-06-03 16:58   ` John Whitington
  1 sibling, 0 replies; 5+ messages in thread
From: John Whitington @ 2015-06-03 16:58 UTC (permalink / raw)
  To: Nils Becker; +Cc: caml-list

Hi Nils,

Nils Becker wrote:
> I find this syntax handy
>
>      let [ii; jj] = List.map float_of_int [i; j] in
>      ... do stuff with the floats
>
> because it avoids repeating the function call. The compiler lets this
> pass but warns that the matching is not exhaustive since [] is not
> matched. This actually can't happen if I'm not mistaken. So, is this
> considered good style, or is there a better idiomatic way to do multiple
> assignments? If yes, should this be an enhancement request for the type
> checker?

If the lengths are almost always small, why not just put appropriate 
functions map_pair, map_tuple3, map_tuple4 etc. into your library?

fun map_tuple3 f (x, y, z) = (f x, f y, f z)

let (ii, jj) = map_pair float_of_int (i, j)

Or, even...

let ii, jj = map_pair float (i, j)

...if you really want to save typing.

John

-- 
John Whitington
Director, Coherent Graphics Ltd
http://www.coherentpdf.com/


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Caml-list] pattern matching on mapped lists
  2015-06-03 16:52   ` Romain Bardou
@ 2015-06-03 17:42     ` Mikhail Mandrykin
  2015-06-03 18:06       ` Octachron
  0 siblings, 1 reply; 5+ messages in thread
From: Mikhail Mandrykin @ 2015-06-03 17:42 UTC (permalink / raw)
  To: caml-list

On 06/03/2015 07:52 PM, Romain Bardou wrote:
> On 03/06/2015 00:23, Nils Becker wrote:
>> I find this syntax handy
>>
>>      let [ii; jj] = List.map float_of_int [i; j] in
>>      ... do stuff with the floats
>>
>> because it avoids repeating the function call. The compiler lets this
>> pass but warns that the matching is not exhaustive since [] is not
>> matched. This actually can't happen if I'm not mistaken. So, is this
>> considered good style, or is there a better idiomatic way to do multiple
>> assignments? If yes, should this be an enhancement request for the type
>> checker?
>>
>> n.
>
> The type-checker cannot find out that List.map returns a list of the 
> same size. I think it would require dependent types. Maybe some GADT 
> can encode this, but it would be a bit messy.
>
> If you use this idiom often, maybe you should define some map 
> functions on tuples, whose length is known at compile-time:
>
> let map2 f (x, y) = f x, f y
>
> let (ii, jj) = map2 float_of_int (i, j) in
> ...
>
> Unfortunately you need to define map2, map3, map4...
>
> Cheers,
>
It seems GADT encoding mostly works here, but the absence of local opens 
in patterns and redefinition of [] constructor and [_; _] special syntax 
for lists currently makes the use of such encoding inconvenient e.g.:

module Flist =
struct

   type z = Z

   type 'a s = S of 'a

   type ('a, _) t =
     | Nil : ('a, z) t
     | :: : 'a * ('a, 'b) t ->  ('a, 'b s) t

     let rec map : type a. _ -> (_, a) t -> (_, a) t = fun f ->
        function
        | Nil ->   Nil
        | x :: xs -> f x :: map f xs
end

open Flist

let a :: b :: c :: Nil = map ((+) 2) @@ 1 :: 2 ::  3 :: Nil;;  (* Can't 
use Flist.[a; b; c] on both sides *)

let d :: e :: Nil = map ((^) "2 + ") @@ "1" :: "2" :: Nil;;

let g :: Nil = map ((+) 2) @@ 1 :: Nil;;

Printf.printf "%d = %s = %d\n%!" a d g;;

BTW, both features are already proposed as feature requests:
https://github.com/ocaml/ocaml/pull/187
https://github.com/ocaml/ocaml/pull/76

Regards, Mikhail


-- 
Mikhail Mandrykin
Linux Verification Center, ISPRAS
web: http://linuxtesting.org
e-mail: mandrykin@ispras.ru


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Caml-list] pattern matching on mapped lists
  2015-06-03 17:42     ` Mikhail Mandrykin
@ 2015-06-03 18:06       ` Octachron
  0 siblings, 0 replies; 5+ messages in thread
From: Octachron @ 2015-06-03 18:06 UTC (permalink / raw)
  To: caml-list

On 06/03/15 19:42, Mikhail Mandrykin wrote:
> It seems GADT encoding mostly works here, but the absence of local 
> opens in patterns and redefinition of [] constructor and [_; _] 
> special syntax for lists currently makes the use of such encoding 
> inconvenient e.g.:
>
> module Flist =
> struct
>
>   type z = Z
>
>   type 'a s = S of 'a
>
>   type ('a, _) t =
>     | Nil : ('a, z) t
>     | :: : 'a * ('a, 'b) t ->  ('a, 'b s) t
>
>     let rec map : type a. _ -> (_, a) t -> (_, a) t = fun f ->
>        function
>        | Nil ->   Nil
>        | x :: xs -> f x :: map f xs
> end
>
> open Flist
>
> let a :: b :: c :: Nil = map ((+) 2) @@ 1 :: 2 ::  3 :: Nil;;  (* 
> Can't use Flist.[a; b; c] on both sides *)
>
> let d :: e :: Nil = map ((^) "2 + ") @@ "1" :: "2" :: Nil;;
>
> let g :: Nil = map ((+) 2) @@ 1 :: Nil;;
>
> Printf.printf "%d = %s = %d\n%!" a d g;;
>
> BTW, both features are already proposed as feature requests:
> https://github.com/ocaml/ocaml/pull/187
> https://github.com/ocaml/ocaml/pull/76
>
> Regards, Mikhail
>

A possibility to lighten these constructions is to use a ppx extension 
to rewrite
the special syntax [a;...] into a standard Cons(a,... Nil)...) 
construction. For instance with my experimental ppx_listlike extension 
(https://github.com/Octachron/ppx_listlike), these examples can be 
rewritten as

     let [%ll? [a; b; c] ] = map ((+) 2) [%ll 1; 2; 3 ];;

or with more syntactic sugar

     let%with_ll [ d; e ] = map ((^) "2 + ") ["1"; "2" ];;
     let%with_ll [g] = map ((+) 2) [1];;

Regards,
octachron.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2015-06-03 18:06 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20150602100015.E87D67EEF7@sympa.inria.fr>
2015-06-02 22:23 ` [Caml-list] pattern matching on mapped lists Nils Becker
2015-06-03 16:52   ` Romain Bardou
2015-06-03 17:42     ` Mikhail Mandrykin
2015-06-03 18:06       ` Octachron
2015-06-03 16:58   ` John Whitington

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).