Haskell „nic nie rób” IO, a jeśli nie inaczej

81

Chcę zrobić w Haskell coś, co wygląda tak:

main1 = do s <- getLine
           if s == "foo" then putStr "You entered foo"

Oczywiście nie jest to legalne, ponieważ nie ma else. Jedna alternatywa, o której myślałem:

nop :: IO ()
nop = sequence_ []

main2 = do s <- getLine
           if s == "foo" then putStr "You entered foo" else nop

To jest trochę rozwlekłe, ale w razie potrzeby zgodziłbym się na to. Byłbym zaskoczony, gdyby nie było wbudowanej wersji programu nop.

Alternatywnie:

doIf :: Bool -> IO () -> IO ()
doIf b m = if b then m else nop

main3 = do s <- getLine
           doIf (s == "foo") (putStr "You entered foo")

Jest to bardziej zwięzłe, ale składnia nie jest szczególnie ładna. Ponownie, nie zdziwiłbym się, gdybym znalazł coś wbudowanego, co już istnieje.

Jaki jest preferowany sposób zrobienia tego?

Dave B.
źródło

Odpowiedzi:

116

Najłatwiejszym sposobem na wykonanie operacji no-op w monadzie jest:

return ()

Odpowiednio:

pure ()

Jednak dla konkretnego idiomu, który robisz, istnieje już kombinator:

import Control.Monad
main = do s <- getLine
          when (s == "foo") $ putStr "You entered foo"

Ten whenkombinator zachowuje się dokładnie tak, jak Twój doIfkombinator :)

bdonlan
źródło
1
Ups, myślałem o funkcji return (), ale myślałem, że faktycznie wróci (tj. Zwróci resztę rzeczy w wyrażeniu do). Mój błąd. Dzięki za wskazanie kiedy.
Dave B
7
powrót to trochę zła nazwa, tak :)
bdonlan
9
@Dave Pamiętaj, że returnw Haskell nie jest konstrukcją językową, to tylko funkcja (o źle dobranej nazwie, jak mówi bdonian). Return nie wpływa na przepływ sterowania, czy coś takiego, co możesz napisać: do {s <- getLine; return (); putStrLn s}to by się wykonało dobrze.
Tom Lokhorst
Dostaję Not in scope: `when'za test = do (when True (putStrLn "Hello")).
Qwertie
3
Ups, whenwymaga import Control.Monadna początku pliku.
Qwertie
21

Można użyć Hoogle znaleźć funkcje, w tym przypadku: when.

W Hoogle możesz wprowadzić sygnaturę typu i spróbuje znaleźć pasujące funkcje w standardowych bibliotekach, ujednolicając typy i zmieniając kolejność argumentów.

W twoim przypadku możesz po prostu wpisać typ swojej doIffunkcji: Bool -> IO () -> IO () . whenjest trzecia odpowiedź tutaj, jej odwrotność unlessjest również tam.

Tom Lokhorst
źródło