Skip to content

Instantly share code, notes, and snippets.

@geekingfrog
Created July 8, 2020 06:32
Show Gist options
  • Save geekingfrog/e9c10e2c8dc49aacc7d0136c67c7918c to your computer and use it in GitHub Desktop.
Save geekingfrog/e9c10e2c8dc49aacc7d0136c67c7918c to your computer and use it in GitHub Desktop.
{-
The idea is to have a way to handle user settings
in an IRC bot. Something like
Set UserTimezone SomeTimeZone
Unset UserTimezone
Set UserDoB (1990, 1, 1)
Unset UserDoB
So I need two things:
1) a way to specify the arguments for a setting key
2) a way to execute these commands, in an arbitrary monad
I'm trying something more advanced than a simple ADT like
SettingCommand
= SetTZ SomeTimeZone
| UnsetTZ
| SetDoB (Int, Int, Int)
| UnsetDoB
I managed 1), but I'm struggling with 2. Below are a few attemps
-}
-- type family to bind arguments to a command
type family SettingArg (key :: Type) :: Type
data UsrTZ = UsrTZ
data UsrDoB = UsrDoB
type instance SettingArg UsrTZ = Text
type instance SettingArg UsrDoB = (Int, Int, Int)
-- the class to actually do stuff
class HandleSettings m a where
set :: a -> (SettingArg a) -> m ()
unset :: a -> m ()
instance (MonadIO m) => HandleSettings m UsrTZ where
set _ _ = pure ()
unset _ = pure ()
instance (MonadIO m) => HandleSettings m UsrDoB where
set _ _ = pure ()
unset _ = pure ()
-- This works but I don't want to have the monad as a type parameter
-- The command parser should not be tied with these details
data UserSettingsCmd m where
Set :: HandleSettings m a => a -> SettingArg a -> UserSettingsCmd m
Unset :: HandleSettings m a => a -> UserSettingsCmd m
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment