前段时间我写了一些代码,它使用OverloadedStrings
从十六进制编码的字符串文字创建ByteString
,它使用base16-bytestring
提供的函数进行解码。这很好用,但似乎我并不像我想的那样理解它。
令我完全困惑的是这个。为什么
{-# LANGUAGE OverloadedStrings #-}
import Data.ByteString.Base16 ()
import qualified Data.ByteString as B
plaintext = "The message" :: B.ByteString
main = print plaintext
编译并运行OK,但如果删除Data.ByteString.Base16
的导入,则无法编译(类似于this question):
test.hs:6:13:
No instance for (Data.String.IsString B.ByteString)
arising from the literal `"The message"'
根据Haskell Wiki,像这样的导入“只对导入类型类的实例很有用”,但据我所知,base16-bytestring源代码没有定义任何类型类实例,只有encode
和decode
函数。
导入如何为编译代码提供必要的IsString
实例?
答案 0 :(得分:32)
在Haskell中,总是会导出和导入类型类实例 - 您无法隐藏它们。这通常被称为“开放世界假设”。
这意味着类型类实例也可以传递地导出:如果你导入一个带有实例的库,它也会从你的模块中导出。
在这种情况下,IsString
实例位于Data.ByteString.Char8
,由Data.ByteString.Base16
导入。您应该能够用以下内容替换导入:
import Data.ByteString.Char8 ()
如果您有兴趣,有一个很好的SO question提供有关开放世界假设的一些信息。