Вы выбрасываете информацию, сохраняя только тот факт, что L ...
содержит список Val a
s в своем типе.Если вы храните эту информацию около
data ValType = TInt | TList ValType
data Val (t :: ValType) where
I :: Int -> Val 'TInt
L :: [Val a] -> Val ('TList a)
, то становится возможным реализовать экземпляр класса IsList
из стандартной библиотеки:
instance IsList (Val ('TList a)) where
type Item (Val ('TList a)) = Val a
fromList = L
toList (L xs) = xs
-- (For completeness, this example requires the OverloadedLists extension)
example :: String
example = show ([I 1, I 2, I 3] :: Val ('TList TInt))
Также обратите внимание, что вы можете реализоватьtoList
.Поскольку этот toList
имеет тип Val ('TList a) -> [Val a]
, он не может быть передан не в списке, поэтому приведенная выше реализация не является частичной.Вы можете проверить этот тип самостоятельно, используя отверстие типа: toList = _
.Вы также можете проверить, что реализация (попытка), подобная следующей, приведет к ошибке типа: toList (I x) = undefined
.
Каждый элемент в списке должен иметь один и тот же тип (нельзя смешивать целые числа со списками внутриодин список, например), но это также относится к исходному коду из вопроса.