Human-readable number of bytes in Haskell
We begin with the "loop". map ((size'/).(1024^)) [0..] is iterate (/1024) size. This has not necessarily the same effect, since (x/y)/y is not the same as x/y² when using floating point arithmetic, but it's fine for our cause. It also works like the Python code, which was your original intention.

We now have

humanReadableBytes :: Integer -&gt; String
humanReadableBytes size | null pairs = printf "%.0fZiB" (size'/1024^7)
                        | otherwise  = if unit=="" then printf "%dB" size 
                                       else printf "%.1f%sB" n unit
where
    (n, unit) = head pairs
    pairs = zip (iterate (/1024) 'size)) units
    size' = fromIntegral size :: Double
    units = ["","Ki","Mi","Gi","Ti","Pi","Ei","Zi"]


And that's all we can improve in terms of terseness at that point without changing your code fundamentally. The main difference between the Python and the Haskell implementation is the mutation of the original num and the early exit from the function.

I would recommend to check the "B" case earlier by the way:

humanReadableBytes :: Integer -&gt; String
humanReadableBytes size
  | abs size &lt; 1024 = printf "%dB" size 
  | null pairs      = printf "%.0fZiB" (size'/1024^7)
  | otherwise       = printf "%.1f%sB" n unit
where
  ...