Haskell: Показать все элементы, которые можно показывать в Hlist
Я пытался
map show . mapMaybe fromDynamic $ [toDyn "one", toDyn (\x -> x::Integer), toDyn 3, toDyn ()]
но он вернулся
["()"]
2 ответа
Ваш код не делает то, что вы ожидаете. Задолго до динамического поведения Data.Dynamic
запускается, проверка типов Haskell разрешает типы. Тип правой части выражения
mapMaybe fromDynamic $ [toDyn "one", toDyn (\x -> x::Integer), toDyn 3, toDyn ()] :: Typeable b => [b]
и тип левой части
map show :: Show a => [a] -> [String]
чтобы объединить их, переменная типа b
соответственно a
становится единым. Если вы скомпилируете это из обычного файла на Haskell, компилятор выдаст вам предупреждение (The type variable `a' is ambigous
). Но в GHCi переводчик по умолчанию ()
,
Но это исправляет тип fromDynamic
в выражении Dynamic -> Maybe ()
, эффективно выбирая все элементы типа ()
,
Если вы заставите компилятор использовать другой тип там, например, указав сигнатуру типа, вы увидите, что fromDynamic
выбирает другой тип:
Prelude Data.Dynamic Data.Maybe> map (show :: Integer -> String) . mapMaybe fromDynamic $ [toDyn "one", toDyn (\x -> x::Integer), toDyn 3, toDyn ()]
["3"]
К сожалению, нет способа достичь того, чего вы хотите: выберите все элементы, тип которых поддерживает экземпляр show, так как эта информация недоступна для fromDynamic
,
Проблема в том, что fromDynamic
должен перейти к мономорфному типу. Это сбор ()
, но с помощью сигнатуры типа вы можете выбрать любой другой тип.
Чтобы показать это, вам понадобится некоторая функция, которая пробует все возможные типы по очереди. Возможно, вы не хотите хранить данные таким образом, но хотите сохранить их в связке с некоторыми операциями (например, show).
Есть два способа связать. Мое любимое, чтобы все функции были предварительно применены к значению (так что для шоу, вы просто получите список групп типа String
).
Другой способ - также поместить функции в Dynamic
(убедитесь, что они правильный мономорфный тип!), а затем используйте dynApply
,