[racket] Constructors for sequences

21 views
Skip to first unread message

Jens Axel Søgaard

unread,
Apr 29, 2012, 8:12:07 AM4/29/12
to Racket List
Given a sequence is there way to get the "constructor" of the sequence?

(sequence-constructor (list 1 2 3)) = list
(sequence-constructor (vector 1 2 3)) = vector
etc

I'd like to use it for a declare-mappable macro that extends functions
of one argument
to map over sequences. As in (sin (list 1 2 3)) = (list (sin 1) (sin
2) (sin 3)).

The sequence-map function is close, but it produces sequences.
Now I could of course hard code the usual suspects, but it seems
somewhat inelegant.

--
Jens Axel Søgaard

____________________
Racket Users list:
http://lists.racket-lang.org/users

Matthias Felleisen

unread,
Apr 29, 2012, 12:43:48 PM4/29/12
to Jens Axel Søgaard, Racket List

What you're really saying is that sequence-map uses the wrong kind of type. Specifically, it should be polymorphic in the sequence constructor instead of mapping everything to the top of the class hierarchy (sequence).

Interesting point is that you described/found this problem in a type-free world.

Question is how we should deal with this in Typed Racket, given our lack of bounded polymorphism

-- Matthias

Sam Tobin-Hochstadt

unread,
Apr 29, 2012, 12:49:25 PM4/29/12
to Matthias Felleisen, Racket List, Jens Axel Søgaard
On Sun, Apr 29, 2012 at 12:43 PM, Matthias Felleisen
<matt...@ccs.neu.edu> wrote:
>
> What you're really saying is that sequence-map uses the wrong kind of type. Specifically, it should be polymorphic in the sequence constructor instead of mapping everything to the top of the class hierarchy (sequence).
>
> Interesting point is that you described/found this problem in a type-free world.
>
> Question is how we should deal with this in Typed Racket, given our lack of bounded polymorphism

The Scala collections classes go to a *lot* of work to make this all
work nicely in a typed setting. But it's way more than just bounded
polymorphism that they use.

>
> -- Matthias
>
>
>
>
> On Apr 29, 2012, at 8:12 AM, Jens Axel Søgaard wrote:
>
>> Given a sequence is there way to get the "constructor" of the sequence?
>>
>> (sequence-constructor (list 1 2 3))  = list
>> (sequence-constructor (vector 1 2 3))  = vector
>> etc
>>
>> I'd like to use it for a declare-mappable macro that extends functions
>> of one argument
>> to map over sequences. As in (sin (list 1 2 3)) = (list (sin 1) (sin
>> 2) (sin 3)).
>>
>> The sequence-map function is close, but it produces sequences.
>> Now I could of course hard code the usual suspects, but it seems
>> somewhat inelegant.
>>
>> --
>> Jens Axel Søgaard
>>
>> ____________________
>>  Racket Users list:
>>  http://lists.racket-lang.org/users
>
>
> ____________________
>  Racket Users list:
>  http://lists.racket-lang.org/users

--
sam th
sa...@ccs.neu.edu

Galler

unread,
Apr 29, 2012, 3:44:26 PM4/29/12
to us...@racket-lang.org
> (sequence-constructor (list 1 2 3)) = list
> (sequence-constructor (vector 1 2 3)) = vector
> etc
>
> I'd like to use it for a declare-mappable macro that extends functions
> of one argument
> to map over sequences. As in (sin (list 1 2 3)) = (list (sin 1) (sin
> 2) (sin 3)).
>

I think you are seeking a distributive mapping of two functions f and g

;(f (g . rest)) -> g (f(arg) . f(arg2).....)

So (I think) the evaluative order of racket becomes the impediment, and not the
type of the sequence


try this:

(require mzlib/defmacro)

(define-macro (distribute . (f g . rest))
`(,g ,@(map (λ (x) `(,f ,x)) rest)))

> (distribute sin list 1 2 3)
(0.8414709848078965 0.9092974268256817 0.1411200080598672)
> (distribute sin vector 1 2 3)
#(0.8414709848078965 0.9092974268256817 0.1411200080598672)

Jens Axel Søgaard

unread,
Apr 29, 2012, 3:56:26 PM4/29/12
to Galler, us...@racket-lang.org
2012/4/29 Galler <lzga...@optonline.net>:

>> (distribute sin list 1 2 3)
> (0.8414709848078965 0.9092974268256817 0.1411200080598672)

This makes the constructor explicit. That's what I want to avoid.

The problem is that a user can define his own type of sequence,
and I'd like my function work with user defined sequences too.

--
Jens Axel Søgaard

Galler

unread,
Apr 29, 2012, 6:08:14 PM4/29/12
to jens...@soegaard.net, us...@racket-lang.org
ok. then it is a type problem, I was wrong.

Asumu Takikawa

unread,
Apr 29, 2012, 6:29:51 PM4/29/12
to Matthias Felleisen, Racket List, Jens Axel Søgaard
On 2012-04-29 12:43:48 -0400, Matthias Felleisen wrote:
> What you're really saying is that sequence-map uses the wrong kind of type. Specifically, it should be polymorphic in the sequence constructor instead of mapping everything to the top of the class hierarchy (sequence).

I don't think this is just a type issue. The sequence that is returned
by `sequence-map` is lazy, even if the original sequence was not. That's
why you can't get the original type.

Cheers,
Asumu

Matthias Felleisen

unread,
Apr 29, 2012, 6:33:45 PM4/29/12
to Asumu Takikawa, Racket List, Jens Axel Søgaard

On Apr 29, 2012, at 6:29 PM, Asumu Takikawa wrote:

> On 2012-04-29 12:43:48 -0400, Matthias Felleisen wrote:
>> What you're really saying is that sequence-map uses the wrong kind of type. Specifically, it should be polymorphic in the sequence constructor instead of mapping everything to the top of the class hierarchy (sequence).
>
> I don't think this is just a type issue. The sequence that is returned
> by `sequence-map` is lazy, even if the original sequence was not. That's
> why you can't get the original type.
>
> Cheers,
> Asumu


Why is it lazy?

Can we add a strict one that is polymorphic (I apologize to the defenders of proper type terminology here for the applying this word to a dynamic aspect of Racket programs) in the sequence type-tag?

-- Matthias

Ryan Culpepper

unread,
Apr 29, 2012, 6:47:53 PM4/29/12
to Matthias Felleisen, Racket List, Jens Axel Søgaard
On 04/29/2012 04:33 PM, Matthias Felleisen wrote:
>
> On Apr 29, 2012, at 6:29 PM, Asumu Takikawa wrote:
>
>> On 2012-04-29 12:43:48 -0400, Matthias Felleisen wrote:
>>> What you're really saying is that sequence-map uses the wrong kind of type. Specifically, it should be polymorphic in the sequence constructor instead of mapping everything to the top of the class hierarchy (sequence).
>>
>> I don't think this is just a type issue. The sequence that is returned
>> by `sequence-map` is lazy, even if the original sequence was not. That's
>> why you can't get the original type.
>>
>> Cheers,
>> Asumu
>
>
> Why is it lazy?
>
> Can we add a strict one that is polymorphic (I apologize to the
> defenders of proper type terminology here for the applying this word
> to a dynamic aspect of Racket programs) in the sequence type-tag?

Another problem is that not all sequence types are polymorphic. For
example, strings are sequences, but strings can contain only characters.
So what would

(sequence-map char->integer "abc")

return? Custom sequence types can add arbitrary additional constraints.

Ryan

Jens Axel Søgaard

unread,
Apr 30, 2012, 3:06:30 AM4/30/12
to Jens Axel Søgaard, Racket List
2012/4/30 Asumu Takikawa <as...@ccs.neu.edu>:

> On 2012-04-29 12:43:48 -0400, Matthias Felleisen wrote:
>> What you're really saying is that sequence-map uses the wrong kind of type. Specifically, it should be polymorphic in the sequence constructor instead of mapping everything to the top of the class hierarchy (sequence).
>
> I don't think this is just a type issue. The sequence that is returned
> by `sequence-map` is lazy, even if the original sequence was not. That's
> why you can't get the original type.

Good point.

However, I don't mind doing some manual labor:

(define (map-sqr a-sequence)
(let ([construct (sequence-constructor a-sequence)])
(apply construct (sequence->list (sequence-map sqr a-sequence)))))

(map-sqr '(1 2 3)) ; => (1 4 9)
(map-sqr #(1 2 3)) ; => #(1 4 9)

--
Jens Axel Søgaard

Sam Tobin-Hochstadt

unread,
Apr 30, 2012, 8:23:45 AM4/30/12
to Ryan Culpepper, Racket List, Jens Axel Søgaard, Matthias Felleisen

I believe that the Scala folks have handled this too. I really
recommend looking a what they've done.
--
sam th
sa...@ccs.neu.edu

Matthias Felleisen

unread,
Apr 30, 2012, 9:56:17 AM4/30/12
to Sam Tobin-Hochstadt, Racket List, Jens Axel Søgaard

On Apr 30, 2012, at 8:23 AM, Sam Tobin-Hochstadt wrote:

>>
>> Another problem is that not all sequence types are polymorphic. For example,
>> strings are sequences, but strings can contain only characters. So what
>> would
>>
>> (sequence-map char->integer "abc")
>>
>> return? Custom sequence types can add arbitrary additional constraints.
>
> I believe that the Scala folks have handled this too. I really
> recommend looking a what they've done.


Ryan: I am not saying that I want polymorphism in the elements of the sequence. I am calling for polymorphism in the constructor.

Sam: since this issue appears to be particularly relevant in the context of Typed Racket, I think you should take ownership of the issue. I am sure there is a paper in this topic, single-authored or lead-authored, for you.

Eli Barzilay

unread,
Apr 30, 2012, 5:57:12 PM4/30/12
to Galler, us...@racket-lang.org
Yesterday, Galler wrote:
>
> try this:
>
> (require mzlib/defmacro)
>
> (define-macro (distribute . (f g . rest))
> `(,g ,@(map (λ (x) `(,f ,x)) rest)))

Off-topic, but it bugs me to see posted examples that use
`define-macro'... Note that using plain macros is not only more
robust, it's also much easier to read and to write. Following the
above macro is IMO much harder than following this:

(define-syntax-rule (distribute f g x ...) (g (f x) ...))

--
((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay:
http://barzilay.org/ Maze is Life!

Reply all
Reply to author
Forward
0 new messages