Working out the details of a type indexed free monad

前端 未结 6 2005
孤城傲影
孤城傲影 2021-02-05 12:51

I\'ve been using a free monad to build a DSL. As part of the language, there is an input command, the goal is to reflect what types are expected by the input primit

6条回答
  •  没有蜡笔的小新
    2021-02-05 13:06

    If you're willing to sacrifice the implicit ordering and use explicit accessors instead, your Action '[Int, Int] could be implemented using ReaderT (HList '[Int, Int]). If you use an existing library like vinyl that provides lenses, you could write something like this:

    -- Implemented with pseudo-vinyl
    -- X and Y are Int fields, with accessors xField and yField
    addTwo :: ReaderT (PlainRec '[X, Y]) Output ()
    addTwo = do
      x <- view (rGet xField)
      y <- view (rGet yField)
      lift . output $ show (x + y) -- output :: String -> Output ()
    

    Type safety is enforced by constraint propagation: rGet xField introduces a requirement that X be a member of the record.

    For a simpler illustration without the type-level machinery, compare:

    addTwo :: ReaderT (Int, Int) IO ()
    addTwo = do
      x <- view _1
      y <- view _2
      lift . putStrLn $ show (x + y)
    

    We lose the ordering property, which is significant loss, particularly if the ordering is meaningful, e.g. represents the order of user interaction.

    Furthermore, we now have to use runReaderT (~ eval). We can't, say, interleave user input with output.

提交回复
热议问题