+module Booking
+
+import iTasks
+import Data.List
+
+:: List a :== [a]
+
+view label value :== viewInformation label [] value
+edit label value :== updateInformation label [] value
+fill label :== enterInformation label []
+
+share label value :== sharedStore label value
+watch label store :== viewSharedInformation label [] store
+
+ok :== const True
+
+// (>>+) :: Task a -> List ( a -> Bool, a -> Task b ) -> Task b
+(>>+) infixl 1
+(>>+) task options :== task >>* map trans options
+where
+ trans ( p, t ) = OnValue (ifValue p t)
+
+// (>>-) :: Task a -> (a -> Task b) -> Task b
+(>>-) infixl 1
+(>>-) task cont = task >>+ [ ( ok, cont ) ]
+
+// (>>|) :: Task a -> Task b -> Task b
+(>>|) infixl 1
+(>>|) task next = task >>- \_ -> next
+
+// (>>?) :: Task a -> List ( String, a -> Bool, a -> Task b ) -> Task b
+(>>?) infixl 1
+(>>?) task options :== task >>* map trans options
+where
+ trans ( a, p, t ) = OnAction (Action a) (ifValue p t)
+
+
+// Data ////////////////////////////////////////////////////////////////////////
+
+:: Seat = Seat Row Pos
+:: Row :== Int
+:: Pos :== Char
+
+:: Person =
+ { first_name :: String
+ , last_name :: String
+ , age :: Int
+ }
+
+:: Booking =
+ { passengers :: List Person
+ , flight_no :: String
+ , seats :: List Seat
+ }
+
+
+// Stores //////////////////////////////////////////////////////////////////////
+
+free_seat_store :: Shared (List Seat)
+free_seat_store = share "Free seats" [ Seat r p \\ r <- [1..6], p <- ['A'..'D'] ]
+
+
+// Checks //////////////////////////////////////////////////////////////////////
+
+// Tasks ///////////////////////////////////////////////////////////////////////
+
+removeElems :: (List a) (List a) -> List a | iTask a
+removeElems xs ys =
+ []
+ // [ y \\ y <- ys, x <- xs | y =!= x ]
+ // filter (\x -> not (elem x ys)) ys
+
+choose_seats :: Int -> Task (List Seat)
+choose_seats n =
+ enterMultipleChoiceWithShared "Pick a seat" [] free_seat_store >>?
+ [ ( "Continue"
+ , \seats -> True//length seats == n
+ , \seats -> upd (removeElems seats) free_seat_store >>| return seats
+ )
+ ]
+
+main :: Task (List Seat)
+main =
+ (forever (watch "Free seats" free_seat_store >>* [OnAction (Action "Refresh") (always (treturn ()))]))
+ ||-
+ (choose_seats 2 >>- view "Chosen seats")
+
+
+// Boilerplate /////////////////////////////////////////////////////////////////
+
+derive class iTask Seat, Person, Booking
+
+Start :: *World -> *World
+Start world = startEngine main world