I don't understand why this thread moved from Programming
to Chat.  Anyhow...


Raul Miller-4 wrote:
> 
> On Thu, Apr 7, 2011 at 6:29 PM, Viktor Cerovski
> <[email protected]> wrote:
>> This kind of typology is essential to get the things right in Haskell.
>> Now,
>>
>> foldr1 :: (a -> a -> a) -> [a] -> a
>>
>> and that's where analogy between foldr1 and / falls through,
>> because in J not only that we don't have to have all the
>> elements of the argument y of u/ to be of the same type,
>> we don't even have to have the return type of u to be the
>> same as that of the elements of y, or, to paraphrase Roger,
>> Reduce is a poor name for / because / does not necessarily
>> reduce anything.
> 
> J's / (called "Insert" in the dictionary) could be modeled in Haskell
> as having type
> 
>    (array -> array -> array) -> array -> array
> 
> But this strict interpretation would I think only be useful if you
> were implementing J in Haskell.   And I would rather think of
> modelling instances of J's run-time types relevant to the sentences
> involved.  Representing the "static typing underlying J's types" would
> be a whole different exercise.
> 
Yes, and all I was saying is since the Haskell is statically typed,
we must consider type signatures, which is an interesting exercise 
even or especially if we consider run-time typing.  Let's take your
type signature for insert

insert ::  (Array -> Array -> Array) -> Array -> Array

[technical point: concrete type names in Haskell should 
be capitalized, or else array would have had the same 
meaning as a]

and ask how can we model Array ?  Well, it should be at least
a union of J scalars and arrays, ie:

type Array = Jscalar | Jarray

So this way we introduce a run-time polymorphism into a 
statically typed program, unless our particular uses of insert are 
sufficiently simple that compiler can resolve which type from the
union will do the job.

Furthermore, the second Array argument of insert, not being 
explicitly a list, would in most cases have a different rank from 
all the other Array arguments. 

In +/i.3, for instance, it would have rank 1, while all the other 
would have rank 0, ie. be Jcscalar.



>>> In contrast, in J, the initial element is the rightmost element of the
>>> list, which means it must be the same type as the rest of the list.
>>
>> Not really.  Let's consider how ,./i. 3 3 works:
>>
>> ,./i. 3 3 === 0 1 2 ,. 3 4 5 ,. 6 7 8
>>
>> The right ,. has two arguments of rank 1 and returns
>> the result of rank 2, namely:
>>
>>   3 6
>>   4 7
>>   5 8
>>
>> Thus, the left ,. has the left argument of rank 1
>> and the right argument of rank 2.
> 
> Ok but I am failing to see where my statement was incorrect.  All of
> the items of the list were rank 1 and this includes that initial
> element which was also rank 1.  The result of the first ,. was not the
> initial element.  (Though, if Haskell defines reduce, I am sure it
> defines it recursively, which brings in another set of issues --
> still, even in Haskell, I think it would be safe to distinguish
> between the initial case and the inductive case.)
> 
My example was to show that although all the elements of 
the array had the same rank, as you correctly said, arguments 
to ,. had different ranks due to the dynamic typing.

This is not related to the beginning of the insertion 
because the inserted verb could produce results of varying 
ranks at any or all points during the execution of u/y.
For example:

   *// i. 3 3
 0  0  0
 0  0  0
 0  0  0

18 21 24
24 28 32
30 35 40

36 42 48
48 56 64
60 70 80

has the right argument of */ first have rank 1, then 2, 
and the result has rank 3.

Can we at least say that the left argument of u will always 
have the same type, namely that of item of y?
I think that's true, but not necessarily a nice feature of J.

Consider for instance  u/&.:>   
This could have been a full-fledged reduce like in LISP, 
had there not been the automatic fill that happens the moment 
argument gets unboxed [I talk about reduce from LISP rather 
than foldr from Haskell just because the analogy with the 
former can be pushed further in the case of J due to the 
dynamic typing].
For example:

   (i.3 3)+(i.3)+3
 3  4  5
 7  8  9
11 12 13

   > +/&.:> (i.3 3);(i.3);3
3 2 4
3 4 5
6 7 8

   >(i.3 3);(i.3);3
0 1 2
3 4 5
6 7 8

0 1 2
0 0 0
0 0 0

3 0 0
0 0 0
0 0 0

   > +/ > (i.3 3);(i.3);3 
3 2 4
3 4 5
6 7 8

I advocated addition of reduce in J some time ago, although
in the mean time I noticed that I can get things done very 
nicely with insert most of the time.

In the cases where reduce is a must, here is a technique that
can be used (obtained from generalization of what I learned from 
you when I tried to implement tacit Gramm-Schmidt 
orthonormalization few years ago):

   acc =: i.3 3

   -`(- acc -~ ])@.(1=#@$@])/i. 3 3
 3  2  1
 1  0 _1
_1 _2 _3

   0 1 2 - 3 4 5 - 6 7 8 - acc
 3  2  1
 1  0 _1
_1 _2 _3

It is exploiting the fact that the rank 1 right argument appears 
exactly once, at the beginning of the insert.  An unfortunate 
aspect of this approach is that it checks the rank of the right 
argument every time the verb is applied.



> Thanks,
> 
> -- 
> Raul
> ----------------------------------------------------------------------
> For information about J forums see http://www.jsoftware.com/forums.htm
> 
> 

-- 
View this message in context: 
http://old.nabble.com/the-design-of--%5C-tp31343248s24193p31358514.html
Sent from the J Chat mailing list archive at Nabble.com.

----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm

Reply via email to