3 ms·
julia> [ (x,y) for x in 1:3, y in 1:x ] ERROR: UndefVarError: x not defined I think the reason for having x and y in different scopes like this is that if th
by DNF2 5y ago
julia> [ (x,y) for x in 1:3, y in 1:x ]
ERROR: UndefVarError: x not defined
I think the reason for having x and y in different scopes like this is that if the range of y depended on the value of x, this wouldn't turn into an array, where you need all dimensions to have regular length. BTW, this extends to arbitrary dimensions.
I take it multidimensional arrays aren't common data structures in Haskell?
- jolmg 5y ago> if the range of y depended on the value of x, this wouldn't turn into an array, where you need all dimensions to have regular length Yes, that's the issue I encountered with the Monad definition. Had to handle the case where y varied, while in the Julia expression that wasn't possible. I thought the comma in Julia's: [ (x,y) for x in 1:3, y in 2:5 ] was like the comma in Haskell's: [ (x,y) | x <- [1..3], y <- [2..5] ] but I see now that the above Haskell expression is actually the following Julia: [ (x,y) for x in 1:3 for y in 2:5 ] > I take it multidimensional arrays aren't common data structures in Haskell? Nope. They're not a core type in the language, and while I did see some packages on a quick search, they unfortunately seem pretty limited. They're either limited to 2 dimensions or low lengths per dimension. Part of the issue is probably that it'd be for the best for the dimensions to be specified in the type signature, in order to make stuff like adding 2 matrices of different dimensions a compile-time error. However, that gets complicated because you have to use numbers in type signatures and also be able to express a variable number of them. It might be workable using the DataKinds extension and 2-tuple type constructors as cons cells, but it sounds messy. Things get a lot simpler if that's just forgotten about and such errors are raised at run-time, but that's just not what one typically strives for when writing Haskell. Tracing bugs from errors raised at run-time is also quite more troublesome than from those raised at compile-time.
- nybble41 5y ago>> I take it multidimensional arrays aren't common data structures in Haskell? > Nope. They're not a core type in the language, and while I did see some packages on a quick search, they unfortunately seem pretty limited. They're either limited to 2 dimensions or low lengths per dimension. The Data.Array module from the `array` package[0] provides arrays for arbitrary "index" types implementing the Ix interface, which includes tuples of arbitrary Ix types for multi-dimensional arrays. Instances of Ix are defined generically for tuples of up to five elements (for five-dimensional arrays) but you can always define more (orphan) instances, or use a custom Ix type with more than five parameters, or even nest tuples so that your index looks like ((a, b, c), (d, e, f), (g, h, i)), which I believe would be equivalent to the 9-tuple index (a, b, c, d, e, f, g, h, i). For vectors with sizes determined at the type level you have Data.Vector.Sized from the `vector-sized` package[1]. This does not directly support multi-dimensional indices as the size type parameter must be of kind KnownNat, but they can be nested, and the type-level size information implies that all the nested vectors will be the same length. [0] https://hackage.haskell.org/package/array-0.5.4.0/docs/Data-Array.html https://hackage.haskell.org/package/array-0.5.4.0/docs/Data-... [1] https://hackage.haskell.org/package/vector-sized-1.4.4/docs/Data-Vector-Sized.html https://hackage.haskell.org/package/vector-sized-1.4.4/docs/...
- jolmg 5y ago> `vector-sized` package[1]. This does not directly support multi-dimensional indices as the size type parameter must be of kind KnownNat, but they can be nested, Oh! That's neat. Nesting would eliminate the need for a list at the type level, and it seems to handle numbers at the type level. That's probably sufficient to write something like a function type (a -> b -> c) -> Vector x a -> Vector y b -> Vector x (Vector y c) Perhaps it can be an operator that can be chained setting the first argument to always be `(,)`. That might roughly do what the comma does in Julia's multidimensional comprehensions. The only bad part of this is that one wouldn't be able to define a Functor instance that works with arbitrary dimensions. It'd have to be one instance for 2 dimensions, one instance for 3 dimensions, etc. For that, I think a list at the type level holding the dimensions would be necessary. EDIT: No, the nesting would prevent proper chaining mentioned operator. Using such an operator twice would result in something like `Vector z (Vector y (Vector x (a, b), c))` instead of the slightly more desirable `Vector z (Vector y (Vector x (a, (b, c)))` that I was thinking. AFAICT, it doesn't seem that either of those suggestions is sufficient for type-safe multidimensional comprehensions in Haskell. They're better than what I found, but they still have their limitations.