2

In Haskell Turtle, sort has the type (Functor io, MonadIO io, Ord a) => Shell a -> io [a]. It takes a stream in the form of a Shell monad, sorts it into a list, but then wraps it in a MonadIO???

This seems counter-intuitive to me. My beginner eyes say that a MonadIO should only be used when interacting with the outside world, which sort doesn't need to do.

I would have expected sort to be (Ord a) => Shell a -> Shell a so it fits into a stream nicely.

Is this an oversight by the package authors, or am I not understanding how sort should be used?

snak
  • 6,483
  • 3
  • 23
  • 33
mikevdg
  • 370
  • 1
  • 7
  • 2
    My guess is `IO [a]` (or any MonadIO) is weaker than `Shell a` because the latter has side-effects for each elements, whereas in a sorted list all side-effects associated with the input list have been already executed. You can always embed a list into a shell if you want. – n. m. could be an AI Jun 07 '22 at 10:30
  • `Shell` is an instance of `Functor` and `MonadIO` (https://hackage.haskell.org/package/turtle-1.5.25/docs/Turtle-Shell.html#t:Shell), so you can think the type of `sort` is `Order a => Shell a -> Shell [a]` if you want. It's just that `sort` is more generic than that. – snak Jun 07 '22 at 14:50

1 Answers1

3

MonadIO io => io [a] is better than Shell a, because Shell is a MonadIO instance and select lifts lists to Shells. So, if you want, you can write your own more specific sort that has the type you like, implemented with the sort provided by turtle:

sortStream :: Ord a => Shell a -> Shell a
sortStream = sort >=> select
Daniel Wagner
  • 145,880
  • 9
  • 220
  • 380
  • This answer does not explain why similar utilities (like nub or uniq) use `Shell a` result type rather than `MonadIO io => io [a]`. – n. m. could be an AI Jun 07 '22 at 17:03
  • 2
    @n.1.8e9-where's-my-sharem. I don't know why for sure, but my guess would be that those utilities cannot have the better type and retain their behavior. The Unix `uniq` can stream its results, and perhaps turtle's `uniq` can too; whereas a thing of type `MonadIO io => io [a]` cannot. (It is in general the case that more polymorphic types cannot behave in as many ways as more monomorphic types -- a fact we exploit often when reasoning about Haskell programs.) – Daniel Wagner Jun 07 '22 at 18:33