utf8DecodeString :: Ptr Word8 -> Int -> IO [Char]
utf8DecodeString ptr len
  = unpack ptr
  where
    !end = ptr `plusPtr` len

    unpack p
        | p >= end = return []
        | otherwise  =
        case utf8DecodeChar# (unPtr p) of
           (# c#, nBytes# #) -> do
                chs <- unpack (p `plusPtr#` nBytes#)
                return (C# c# : chs)
utf8DecodeString :: Ptr Word8 -> Int -> IO [Char]
utf8DecodeString ptr len
  = unpack ptr
  where
    !end = ptr `plusPtr` len

    unpack p
        | p >= end = return []
        | otherwise  =
        case utf8DecodeChar# (unPtr p) of
           (# c#, nBytes# #) -> do
                chs <- unpack (p `plusPtr#` nBytes#)
                return (C# c# : chs)
utf8DecodeString ptr len
  = unpack ptr
  where
    !end = ptr `plusPtr` len

    unpack p
        | p >= end = return []
        | otherwise  =
        case utf8DecodeChar# (unPtr p) of
           (# c#, nBytes# #) -> do
                chs <- unpack (p `plusPtr#` nBytes#)
                return (C# c# : chs)