2012-03-15 17 views
8

Często chciałbym wprowadzić regularne funkcje do sekwencji "binded". Jak w tym przykładzie contrived:Sekwencjonowanie wiąże się z czystymi funkcjami

getLine >>= lift (map toUpper) >>= putStrLn 

muszę zdefiniować funkcję podnoszenia lift :: (a -> b) -> a -> m b do tej pracy. Problem polega na tym, że nie znam takiej funkcji, i nie wydaje mi się, że jest to Hoogle. Uważam, że to dziwne, ponieważ to ma dla mnie sens.

Prawdopodobnie istnieją inne sposoby, aby to zadziałało, ale podoba mi się sposób, w jaki bezdotykowy kod pozwala mi przeskanować linię w jednym przejściu, aby dowiedzieć się, co się dzieje.

let lift f x = return (f x) in 
getLine >>= lift (map toUpper) >>= putStrLn 

Moje pytanie sprowadza się do tego: czy brakuje mi czegoś lub jak to się dzieje, że nie ma funkcji takiej jak winda. Moje doświadczenie w Haskell jest nadal bardzo ograniczone, więc zakładam, że większość ludzi rozwiązuje to w inny sposób. Czy ktoś może mi wytłumaczyć idiomatyczny sposób rozwiązania tego problemu.

Odpowiedz

18

Istnieją trzy sposoby idiomatyczne.

  1. Nie używaj wiązania; użyć pierwszego trafienia na poszukiwaniu Hoogle zamiast:

    liftM (map toUpper) getLine >>= putStrLn 
    

    Istnieje wiele alternatywnych pisowni liftM, takich jak fmap lub (<$>).

  2. Inline funkcja lift zdefiniowano:

    getLine >>= return . map toUpper >>= putStrLn 
    
  3. wykorzystać prawa monada bezpiecznik dwie ostatnie wiąże się w opcji 2:

    getLine >>= putStrLn . map toUpper 
    
+1

chciałbym umieścić 'foo >> = return. bar >> = baz' na końcu listy. W dłuższych łańcuchach jest to dobre, ale w krótkich przypadkach, jak na przykład, 'foo >> = baz. bar "jest znacznie bardziej czytelny IMO. –

+0

Właściwie myślę, że 'foo >> = return. bar >> = baz' to schludny sposób. Nie przyszło mi do głowy, że to właśnie jest funkcja windy, której szukałem. –

+4

'putStrLn. map toUpper = << getLine' wygląda całkiem schludnie. Lubię używać '= <<', ponieważ przypomina to funkcję aplikacji. – danr

3

Użyj instancji Functor w takich przypadkach:

> import Data.Char 
> import Data.Functor 
> map toUpper <$> getLine >>= putStrLn 
foo 
FOO 
> 
Powiązane problemy