
For instance, if we consider just join, with the above definition:
join [[1,2],[3]] = [1, _|_]
Which, I think, is fairly undesirable. You can try to avoid bottoms like so: Well, there is a trick you can use here: wrap everything in a Maybe. Not that it helps with the efficiency issue, but at least you can mark the empty spots of the diagonal, since it's possible to check the length of the list before extracting its nth element. Which leads to some kind of MaybeZipList:
newtype MaybeZipList a = MZL { getMZL :: [Maybe a] } deriving Show instance Monad MaybeZipList where return = MZL . repeat . Just MZL mxs >>= f = MZL $ zipWith bind mxs [0..] where bind mx n = do x <- mx let ys = getMZL (f x) if length (take (n+1) ys) <= n then Nothing else ys !! n But it's still not perfect, since the laws only apply modulo extra Nothings at the end of the resulting lists...
This monad works fine for size enforced vectors Sure, I just can't see any good use for those. After all, if you use arrays, you have to keep the whole structure in the memory just to discard most of it.
Thanks for all the answers! Gergely -- http://www.fastmail.fm - Or how I learned to stop worrying and love email again