Ответ 1
После просмотра руководств GHC и вокруг Haskell wiki (особенно Список экземпляров), у меня есть лучшая идея как это работает. Вот краткое изложение того, что я узнал:
Проблема
Haskell Report определяет объявление экземпляра следующим образом:
Тип (T u 1... u k) должен иметь вид конструктор типа T, примененный к простым переменным типа u 1,... u k; кроме того, T не должен быть синонимом типа, а u i должен быть различным.
Части, выделенные жирным шрифтом, являются ограничениями, которые меня подстегнули. На английском языке они:
- Все, что после конструктора типа должно быть переменной типа.
- Вы не можете использовать псевдоним типа (используя ключевое слово
type
), чтобы обойти правило 1.
Итак, как это связано с моей проблемой?
[Word16]
- это еще один способ записи [] Word16
. Другими словами, []
- это конструктор, а Word16
- его аргумент.
Итак, если мы попытаемся написать:
instance IsString [Word16]
что совпадает с
instance IsString ([] Word16) where ...
он не будет работать, потому что он нарушает правило 1, как компилятор любезно указывает.
Попытка скрыть его в синониме типа с
type String16 = [Word16]
instance IsString String16 where ...
тоже не будет работать, потому что он нарушает часть 2.
Таким образом, невозможно получить [Word16]
(или список чего угодно, если на то пошло) реализовать IsString
в стандартном Haskell.
Введите... (барабаньте пожалуйста)
Решение №1: newtype
Решение @ehird предложило обернуть его в newtype
:
newtype String16 = String16 { unString16 :: [Word16] }
instance IsString String16 where ...
Он обходит ограничения, потому что String16
больше не является псевдонимом, это новый тип (извините за каламбур)! Единственным недостатком этого является то, что мы должны обертывать и разворачивать его вручную, что раздражает.
Решение №2: Гибкие экземпляры
За счет переносимости мы можем полностью отказаться от ограничений с помощью гибких экземпляров:
{-# LANGUAGE FlexibleInstances #-}
instance IsString [Word16] where ...
Это было решение @[Даниэль Вагнер].
(Кстати, я закончил создание обертки foldl'
вокруг Data.Text.Internal и написал хэш поверх этого.)