2013-02-04 24 views
5

PróbowałemHaskell: Zobacz wszystkie elementy, które są "showable" na Hlist

map show . mapMaybe fromDynamic $ [toDyn "one", toDyn (\x -> x::Integer), toDyn 3, toDyn()] 

ale wrócił

["()"] 
+1

Czy na pewno chcesz przechowywać dane wymieszane na takiej liście? – AndrewC

+0

Można na przykład użyć rekordu do łatwiejszego przechowywania danych i łatwo będzie można korzystać z funkcji takich jak show na elementach, ponieważ typy są dostępne w środowisku wykonawczym. Posiadanie typów naprawionych w czasie wykonywania jest zaletą, a nie wadą, więc powinieneś to robić, gdy tylko jest to możliwe. – AndrewC

+0

Ten problem został stworzony w celu zilustrowania mojego problemu. Projekt, nad którym pracuję, jest tutaj github.com/rbarreiro/farofias Kolejnym krokiem w projekcie jest dodanie funkcji, które nie są instancją Data.Data. – rbarreiro

Odpowiedz

5

Twój kod nie spełnia Twoich oczekiwań. Na długo przed dynamicznym zachowaniem się Data.Dynamic, sprawdzanie typu Haskell rozwiązuje typy. Rodzaj prawej części wyrażenia jest

mapMaybe fromDynamic $ [toDyn "one", toDyn (\x -> x::Integer), toDyn 3, toDyn()] :: Typeable b => [b] 

i rodzaj lewej części jest

map show :: Show a => [a] -> [String] 

tak aby połączyć je, typ zmiennej b wzgl. a zostaje ujednolicony. Jeśli skompilowałbyś to ze zwykłego pliku Haskella, kompilator dałby ci ostrzeżenie (The type variable `a' is ambigous). Ale w GHCi interpreter domyślnie przyjmuje wartość ().

Ale to naprawia typ fromDynamic w wyrażeniu na Dynamic -> Maybe(), skutecznie wybierając wszystkie elementy typu ().

Jeśli wymusisz na kompilatorze użycie innego typu, np. podając sygnaturę typu, widać, że fromDynamic wybiera inny typ:

Prelude Data.Dynamic Data.Maybe> map (show :: Integer -> String) . mapMaybe fromDynamic $ [toDyn "one", toDyn (\x -> x::Integer), toDyn 3, toDyn()] 
["3"] 

Niestety, nie ma sposobu, aby osiągnąć to, co chcesz: Wybierz wszystkie elementy, których rodzaj wsparcia instancji show, jako że informacja nie jest dostępna do fromDynamic.

7

Problemem jest to, że musi iść do fromDynamic typu jednokształtnym. Pobiera (), ale z podpisem typu można wybrać dowolny inny typ.

Aby to pokazać, potrzebowałbyś jakiejś funkcji, która po kolei próbuje wszystkich możliwych typów. Prawdopodobnie nie chcesz przechowywać takich danych, ale chcesz przechowywać je w pakiecie z niektórymi operacjami (takimi jak show).

Są dwa sposoby pakowania. Moim faworytem jest, aby wszystkie funkcje były wstępnie zastosowane do wartości (tak, aby pokazać, po prostu otrzymasz listę dźwięków typu String).

Innym sposobem jest również wstawienie funkcji do Dynamic (upewnij się, że są to prawidłowe typy monomorficzne!), A następnie użyj dynApply.

+1

fajny pomysł: "zapisz go w pakiecie z niektórymi operacjami" – rbarreiro