4

I'm passing a (strict) ByteString to something expecting a System.IO.FilePath, which is declared as type FilePath = String. I'm also using {-# LANGUAGE OverloadedStrings #-}. I've had conversions in some places happen automatically, but here it does not. What have I got wrong?

Main.hs:33:40: error:
    • Couldn't match type ‘ByteString’ with ‘[Char]’
      Expected type: FilePath
        Actual type: ByteString
Matt Joiner
  • 112,946
  • 110
  • 377
  • 526

2 Answers2

13

The {-# LANGUAGE OverloadedStrings #-} pragma only works for string literals, like "a string". In that case, Haskell implicitly places a fromString before every string literal, so it rewrites a string literal as "a string" to fromString "a string". This only happens for literals.

In Haskell, as far as I know, there are no implicit conversions. Conversions between for instance Int and Float are all explicit.

Furthermore note that the IsString typeclass only has a function fromString :: String -> a. So that means it works only from a string to that instance (here ByteString), not the other way around.

You can use the unpack :: ByteString -> String to convert the ByteString to a String.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • 4
    But do note that `unpack` is simply wrong for most encodings. And of course also beware that the meaning of a `FilePath` *also* depends on an encoding setting that's hidden behind the scenes. If you are on Linux, you can avoid a lot of headaches by simply using a file API that uses `ByteString` for the name of its files in the first place. – Daniel Wagner Feb 22 '18 at 13:37
4

IIRC, the OverloadedStrings extension doesn't enable magical conversion between different types of data. What it does is that when you write a string literal like "foo", the compiler can treat that literal as not only a String, but also as a ByteString.

You probably need something like unpack to convert ByteString to String.

Mark Seemann
  • 225,310
  • 48
  • 427
  • 736