2011-09-10 14 views
8

Cudowna rzecz o Haskell. Rodzaj funkcji prawie dyktuje jej realizację. To sprawa dla tego jednego, ale ... mój mózg po prostu nie jest owijanie wokół zagnieżdżonych funkcji rzecz tutaj:Jak zaimplementować tę funkcję w Haskell

mkDyn :: (Typeable a) => ((a -> IO()) -> IO()) -> ((Dynamic -> IO()) -> IO()) 

Pytanie tylko, jak radzić obsługi błędów w fromDynamic zaproszenia, które będą wymagane, ale ... Mogę sobie z tym poradzić, gdy resztę wymyślę. Zgaduję, że gdzieś będzie coś takiego. Ale wydaje mi się, że nie udało mi się zrozumieć owijania lambdy.

case fromDynamic x of 
    Just x -> f x 
    Nothing -> undefined -- TODO 
+1

Wow, nie wiedziałem nawet, że Haskell ma wsparcie dynamiczne, nie mówiąc już o tym, że był [dostępny w bazie] (http://hackage.haskell.org/packages/archive/base/latest/doc/html/ Data-Dynamic.html). Naucz się czegoś nowego każdego dnia. –

+0

@Joey IIRC jest nawet biblioteka do pisania imperatywnego kodu z łatwymi operatorami przypisania, ale zapomniałem gdzie. Myślę, że raz wspomniano o niej na Planet Haskell. – fuz

Odpowiedz

10

myślę chcesz toDyn nie fromDynamic. Więc zróbmy to powoli:

mkDyn :: Typeable a => 
     ((a -> IO()) -> IO()) 
     -> (Dynamic -> IO()) 
     -> IO() 
mkDyn k f = ... 

Nasz typ zwracany powinien być IO() i możemy uzyskać, że albo dzwoniąc k lub f. Dzwonienie pod numer f nie pomaga nam zbytnio, ponieważ w jakiś sposób zmaterializujemy Dynamic, ale nie możemy tego zrobić (rozsądnie) z k. Dlatego chcemy zadzwonić pod numer k. k potrzebuje innej funkcji jako argumentu, więc zacznijmy tak:

mkDyn k f = k (\a -> ...) 

Więc argument funkcja jest Typeable a => a -> IO(). Nie posiadamy funkcji tego typu, ale posiadamy funkcję typu Dynamic -> IO(). Ze względu na Typeable przymusu możemy użyć toDyn aby zwrócić a do Dynamic i dostać.

mkDyn k f = k (\a -> f (toDyn a)) 

Istnieją prostsze implementacje (np return() lub k (\a -> return()), ale ten wydaje się mieć sens

+0

mkDyn k f = k $ f. toDyn – rampion

+3

@rampion Two może grać w tę grę! 'mkDyn = (. (. toDyn))'. –

+2

Ja preferuję wskazane wersje. Używam tylko stylu bez punktów, jeśli rzeczy naprawdę są prostymi potokami. Wszystko (nawet nieznacznie) bardziej skomplikowane i żałowałem, gdy następnym razem przeczytam kod. – nominolo

4

oszukiwałem i użył Djinn program

raz pierwszy uogólniony typ danych.

f :: (a -> c) 
    -> ((a -> b) -> b) 
    -> ((c -> b) -> b) 

Funkcja (a -> c) reprezentuje funkcję toDyn function, a c reprezentuje Dynamic. b reprezentuje IO().

Djinn wynikają była zaskakująco prosta:

@djinn (a -> c) -> ((a -> b) -> b) -> ((c -> b) -> b) 
f a b c = b (\ d -> c (a d)) 

czyniąc ją bardziej specyficzne (zastępując (a -> c) z funkcją toDyn), otrzymujemy:

mkDyn :: (Typeable a) => ((a -> IO()) -> IO()) -> ((Dynamic -> IO()) -> IO()) 
mkDyn b c = b (\ d -> c (toDyn d)) 

który pasuje nominolo's answer.

+1

Czy to dowodzi, że nominolo to dżin? – Landei

Powiązane problemy