Created
January 30, 2022 23:19
-
-
Save Sintrastes/33a42854c006d292c2ca30d77a4e5c9a to your computer and use it in GitHub Desktop.
Example of using a comonadic like structure to build a dialog tool.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- class KComonad m w where | |
-- extractM :: w a -> m a | |
-- extendM :: (w a -> m b) -> w a -> m (w b) | |
-- duplicateM :: w a -> m (w (w a)) | |
-- A variation on the Moore comonad | |
-- that allows for a termination condition. | |
-- Q: What kind of structure is this? | |
-- I think this is a monadic comonad with additional | |
-- structure. | |
data MooreE s e a = | |
MooreE s (e -> Either a (MooreE s e a)) | |
-- Q: Is this a monadic comonad? | |
data MooreM m e s = | |
MooreM s (e -> m (MooreM m e s)) | |
data DialogViewModel = | |
DisplayMessage { | |
message :: String, | |
saidBy :: String | |
} | |
| DisplayPrompt { | |
promptMessage :: String, | |
promptedBy :: String, | |
options :: [String], | |
selected :: Int | |
} | |
data DialogEvent = | |
MoveCursorUp | |
| MoveCursorDown | |
| PressEnter | |
type Dialog = MooreM Maybe DialogEvent DialogViewModel | |
data Free f a = | |
Free (f (Free f a)) | |
| Pure a | |
data DialogF a = | |
SayF String String a | |
| PromptF String String [(String, DialogMonad ())] a | |
type DialogMonad a = Free DialogF a | |
say :: String -> String -> DialogMonad () | |
say = undefined | |
prompt :: String -> String -> [(String, DialogMonad a)] -> DialogMonad a | |
prompt = undefined | |
dialog :: Free DialogF () -> Maybe Dialog | |
dialog (Pure _) = Nothing | |
dialog st@(Free (SayF player msg rest)) = Just $ | |
MooreM (DisplayMessage msg player) $ \event -> | |
case event of | |
PressEnter -> dialog rest | |
otherwise -> dialog st | |
dialog st@(Free (PromptF player msg options rest)) = | |
dialogPrompt player msg options rest 0 | |
where | |
dialogPrompt player msg options rest selected = pure $ | |
MooreM (DisplayPrompt msg player (map fst options) selected) $ \event -> | |
case event of | |
MoveCursorUp | selected < length options - 1 -> | |
dialogPrompt player msg options rest (selected + 1) | |
MoveCursorDown | selected > 0 -> | |
dialogPrompt player msg options rest (selected - 1) | |
PressEnter -> dialog rest | |
otherwise -> dialogPrompt player msg options rest selected | |
{- | |
exampleDialog :: Dialog () | |
exampleDialog = dialog $ do | |
say "player_1" "hello!" | |
prompt "player_1" "What would you like to do?" | |
[ | |
("A", do | |
say "player_1" "Great!"), | |
("B", do | |
say "player_1" "Ok." | |
say "player_1" "See you tomorrow.") | |
] | |
-} | |
main = do | |
putStrLn "Hello" | |
putStrLn "World" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment