diff --git a/koans/basic/9-input/Koan.hs b/koans/basic/9-input/Koan.hs new file mode 100644 index 0000000..df9dab3 --- /dev/null +++ b/koans/basic/9-input/Koan.hs @@ -0,0 +1,46 @@ +{- | Input! + +We want to react to user input. For this track, let's allow the program to interact on the console. +To do this, meditate about the follow sentence: + +Events in Rhine come from event clocks. + +An event happens when an event clock ticks. +For example, to react every time when a line is entered on the standard input, +you have to add the 'Stdin' event clock to your main Rhine. + +Events are handled just like any other kind of data. +The difference between event clocks and clocks like 'Millisecond n' is only conceptual: +A fixed rate clock ticks at predictable intervals, +whereas it depends on the user or another external influence when an event clock ticks. +The frameworks handles them in the same way. + +The next Koans are about the event that is triggered when a line of text is entered on the standard input. +-} +module Koan where + +-- text +import Data.Text.IO as Text (putStrLn) + +-- rhine +import FRP.Rhine + +{- | A line of user input. + +The 'Stdin' clock ticks every time a line is entered on stdin. + +The information _what_ was typed can be retrieved with a special signal function: 'tagS'. +This signal function is a "sensor" (it has no input, only output), +and it produces different data depending on the clock. +For 'Stdin', it is one line of standard input. +-} +userInput :: ClSF IO Stdin () Text +userInput = tagS + +-- | Output the same line that was just entered. +parrot :: ClSF IO Stdin () () +-- Do you remember how to convert an effectful function into a ClSF? +parrot = userInput >-> _ Text.putStrLn + +main :: IO () +main = flow mainRhine diff --git a/koans/basic/9-input/Test.hs b/koans/basic/9-input/Test.hs new file mode 100644 index 0000000..bc73546 --- /dev/null +++ b/koans/basic/9-input/Test.hs @@ -0,0 +1,19 @@ +module Main where + +-- rhine-koan +import Koan qualified (main) + +-- test-io +import TestIO + +main :: IO () +main = testForSeconds 2 Nothing Koan.main $ \output -> + case length (filter (== "Hello Rhine!") output) of + 10 -> [] + 0 -> ["Your program didn't produce the line \"Hello Rhine!\" in time. Maybe a typo?"] + n + | n < 10 -> + [ "Your program seems to be running a bit slow." + , "Only " ++ show n ++ " messages arrived." + ] + _ -> ["It seems the clock is ticking too fast."]