A software engineer website

Polysemy: Input

Gautier DI FOLCO January 04, 2023 [Haskell] #haskell #polysemy #design #effects systems

Whenever you might have varying strategies to fetch some data, you might want to use Input:

data Input i m a where
  Input :: Input i m i

it comes with three interpreters:

runInputConst :: i -> Sem (Input i ': r) a -> Sem r a
runInputConst c = interpret $ \case
  Input -> pure c

usable as:

runInputConst @String "Hello, world!" $ input >>= embed . putStrLn
runInputList ::
  [i] ->
  Sem (Input (Maybe i) ': r) a ->
  Sem r a
runInputList is =
  evalState is
    . reinterpret
      ( \case
          Input -> do
            s <- gets uncons
            for_ s $ put . snd
            pure $ fst <$> s
      )

usable as:

    runInputList @Char "Hello" $ whileJust (input @(Maybe Char)) $ embed . print
runInputSem :: forall i r a. Sem r i -> Sem (Input i ': r) a -> Sem r a
runInputSem m = interpret $ \case
  Input -> m

usable as:

message <- embed $ newMVar @String "Hello, world!"
runInputSem (embed $ tryTakeMVar message) $ whileJust (input @(Maybe String)) $ embed . putStrLn

See the full the code here.