だから私は何か斬新なことをしようとしていますが (私はそう思います)、Haskell 型レベルのプログラミングの経験が十分ではなく、それを自分で解決することができません。
実行するいくつかの効果を記述した無料のモナドを持っています (それがあなたのやり方なら AST です)。期待される効果の説明に対してそれを解釈したいと思います。
これまでの私のコードは次のとおりです::
{-# LANGUAGE DeriveFunctor, FlexibleInstances, GADTs, FlexibleContexts #-}
import Control.Monad.Free -- from package 'free'
data DSL next
= Prompt String (String -> next)
| Display String next
deriving (Show, Functor)
prompt p = liftF (Prompt p id)
display o = liftF (Display o ())
-- |Just to make sure my stuff works interactively
runIO :: (Free DSL a) -> IO a
runIO (Free (Prompt p cont)) = do
putStr p
line <- getLine
runIO (cont line)
runIO (Free (Display o cont)) = do putStrLn o; runIO cont
runIO (Pure x) = return x
それが「コア」コードです。プログラムの例を次に示します。
greet :: (Free DSL ())
greet = do
name <- prompt "Enter your name: "
let greeting = "Why hello there, " ++ name ++ "."
display greeting
friendName <- prompt "And what is your friend's name? "
display ("It's good to meet you too, " ++ friendName ++ ".")
このプログラムをテストするために、次runTest :: Free DSL a -> _ -> Maybe a
のようにプログラムと「期待される効果」の仕様を漠然と取るfunction を使用したいと思います。
expect = (
(Prompt' "Enter your name:", "radix"),
(Display' "Why hello there, radix.", ()),
(Prompt' "And what is your friend's name?", "Bob"),
(Display' "It's good to meet you too, Bob.", ()))
そして、プログラムが実行する各効果をリスト内の次の項目と照合することにより、プログラムを解釈しexpect
ます。次に、関連付けられた値 (各ペアの 2 番目の項目) が、その効果の結果としてプログラムに返されます。すべての効果が一致する場合、プログラムの最終結果は として返されますJust
。何かが一致しない場合は、Nothing
返される必要があります (後で、有益なエラー メッセージを返すようにこれを拡張します)。
もちろん、このタプルは役に立ちません。その型は非常に巨大なものであり、ジェネリック関数をexpect
書き込めないからです。runTest
私が抱えている主な問題は、どのようなプログラムに対してもどのようなシーケンスでも機能する関数を記述できるように、この予想される意図のシーケンスをどのように表現すべきかということですFree DSL a
。
- Haskell のさまざまな高度な型レベルの機能については漠然と認識していますが、どの機能を使用する必要があるかについてはまだ経験がありません。
- シーケンスに HList などを使用する必要があり
expected
ますか?
調べるためのヒントは大歓迎です。