Skip to content

Instantly share code, notes, and snippets.

@ChrisPenner
Last active June 19, 2017 04:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ChrisPenner/fed3d97c6b5f37c1048af3bffdc8d653 to your computer and use it in GitHub Desktop.
Save ChrisPenner/fed3d97c6b5f37c1048af3bffdc8d653 to your computer and use it in GitHub Desktop.
Commands as a Ring
module CommandRing where
class (Monoid g) => Ring g where
identity :: g
identity = mempty
plus :: g -> g -> g
plus = mappend
invert :: g -> g
mult :: g -> g -> g
data Cmd =
Mv FilePath FilePath
| Rm FilePath
| Restore FilePath
| Sequence [Cmd]
| Concurrent [Cmd]
| Noop
deriving (Show, Eq)
instance Monoid Cmd where
mempty = Noop
Noop `mappend` cmd = cmd
cmd `mappend` Noop = cmd
Concurrent cmds `mappend` Concurrent cmds' = Concurrent (cmds ++ cmds')
cmd `mappend` cmd' = Concurrent [cmd, cmd']
instance Ring Cmd where
invert (Mv src dest) = Mv dest src
invert Noop = Noop
invert (Restore fp) = Rm fp
invert (Rm fp) = Restore fp
invert (Sequence cmds) = Sequence (invert <$> L.reverse cmds)
-- Not sure if the Group laws hold for this case...
invert (Concurrent cmds) = Concurrent (invert <$> cmds)
Sequence cmd `mult` Sequence cmd' = Sequence (cmd ++ cmd')
cmd `mult` Noop = cmd
Noop `mult` cmd = cmd
cmd `mult` cmd' = Sequence [cmd, cmd']
@DrBoolean
Copy link

Thanks for this!

Now that I see it, I suppose the Seq/Par stuff is its own ring and Cmd could just be a group.

@ChrisPenner
Copy link
Author

@DrBoolean Yeah that definitely makes sense!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment