13 ms·
The Haskell one is polymorphic with respect to rank (and is indeed polymorphic even with respect to whether it's backed by a data structure or not). Haskell's
by dwohnitmok 5y ago
The Haskell one is polymorphic with respect to rank (and is indeed polymorphic even with respect to whether it's backed by a data structure or not).
Haskell's infelicities for numeric code come from other places.
- moonchild 5y agoFor those haskell functions which operate on lists of arbitrary items, the items can indeed be themselves lists. However, the code is still fundamentally item-oriented. Those haskell functions which operate on lists of specific types (such as 'lowers', which operates on lists of characters) cannot readily be applied to higher-ranked lists of the same.
- dwohnitmok 5y agoI suspect you mean `toLower`? In that case yes it can (and again generalized to many other contexts rather than just higher dimensional data structures), you just use lifted function application (that is `<$>`) instead of normal function application (that is `$`). (The item-oriented way of thinking about this, which is equivalent, is you use `fmap`).
- moonchild 5y agoI mean the 'lowers' function from the linked post, which counts the lowercase characters of its input. In this case the apl function returns an array of rank one less than its input, where each item is the number of lowercase characters at the given position along the reduced axis. I don't think this can be expressed using fmap. (I'm not sure what <$> is, but judging from [0] it seems to be syntactic sugar for fmap?) You would at least the more powerful 'reduce' (or some analogue thereof), and I'm not even sure if that would be sufficient to properly express the rank operator. 0. https://wiki.haskell.org/Functor#Related_Functions https://wiki.haskell.org/Functor#Related_Functions EDIT: the problem with the rank operator is ensuring the array remains rectangular. (I know haskell lists are not rectangular; imagining a type which was.) APL punts on this by being dynamically typed, but you would have to solve that problem somehow. 'Reshape' suffers somewhat the same problem, and I'm not sure it can be typed sensibly.
- dwohnitmok 5y agoAh I see. Right so the 0th rank version you've presented here could be written as -- Assume countLower exists and is [Char] -> Int lowers : Functor f => f [Char] -> f Int lowers xs = countLower <$> xs -- Also: lowers = fmap countLower This `lowers` works for rank 0 across arbitrary rank collections so you can have as many nestings you'd like. Now if you want to vary the rank at compile time, that is possible by generalizing `countLower` away from a concrete list and instead to something like `Traversable`. The issue as you point out is if you want to vary the rank at runtime, which is easy to do in APL and other array-based programming languages, and which is quite difficult to do in a way that plays well with Haskell's type system (you could eject and instead use dynamic typing in Haskell instead, but that is probably going to look quite different from the rest of your Haskell code). And this indeed is part of the infelicities I was talking about. To really type this well you need dependent types, which you can kind of do in Haskell, but it rapidly becomes very messy.