Импорт Haskell имеет побочные эффекты?
Я написал код некоторое время назад, который использует OverloadedStrings
для создания ByteString
из строковых литералов с шестнадцатеричным кодированием, которые он декодирует, используя функции, предоставляемые base16-bytestring
. Это сработало хорошо, но, похоже, я не понял его так хорошо, как я думал.
Вещь, которая меня полностью запутала, такова. Почему
{-# LANGUAGE OverloadedStrings #-}
import Data.ByteString.Base16 ()
import qualified Data.ByteString as B
plaintext = "The message" :: B.ByteString
main = print plaintext
скомпилировать и запустить ОК, но если я удалю импорт для Data.ByteString.Base16
, тогда он не сможет скомпилировать (похоже на этот вопрос):
test.hs:6:13:
No instance for (Data.String.IsString B.ByteString)
arising from the literal `"The message"'
В соответствии с Haskell Wiki импорт, подобный этому, "полезен только для импорта экземпляров типов и ничего другого", но как я вижу, исходный код base16-bytestring не определяет экземпляры typeclass, а только функции encode
и decode
.
Как этот импорт предоставляет необходимый экземпляр IsString
для компиляции кода?
Ответы
Ответ 1
В Haskell экземпляры typeclass всегда экспортируются и импортируются - вы не можете их скрыть. Это обычно называют "открытым мировым допущением".
Это означает, что экземпляры typeclass также экспортируются транзитивно: если вы импортируете библиотеку с экземпляром, она также экспортируется из вашего модуля.
В этом случае экземпляр IsString
находится в Data.ByteString.Char8
, который импортируется Data.ByteString.Base16
. Вы должны иметь возможность заменить свой импорт:
import Data.ByteString.Char8 ()
Есть хороший вопрос SO, дающий некоторую информацию о предположении открытого мира, если вы заинтересованы.