3 ms·
Ah 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 =>
by dwohnitmok 5y ago
Ah 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.