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
