packages feed

acme-inator (empty) → 0.1.0.0

raw patch · 4 files changed

+168/−0 lines, 4 filesdep +basesetup-changed

Dependencies added: base

Files

+ Acme/Inator.hs view
@@ -0,0 +1,111 @@+-- |+-- Module:      Acme.Inator+-- License:     Public Domain+-- Maintainer:  Mark Lentczner <mzero@glyphic.com>+-- Stability:   unstable, may self-destruct+-- Portability: portable+--+-- Construction and operation of evil inventions in the Tri-State area.+-- Based on the pioneering work of Dr. Heinz Doofenschmirtz.++module Acme.Inator (+    -- * Evil Inventions+    EvilInvention,+    inator, selfDestruct,++    -- * Secret Agents+    Agent(..),+    perryThePlatypus,+    TrappedAgent,++    -- * The TriStateArea+    TriStateArea,+    activate,+    whileTrapping,+) where++import Control.Monad (liftM)++-- | An 'EvilInvention' is like a normal function @a -> b@, only used in evil+-- plans. It will only function in the context of a 'TrappedAgent'. See+-- 'activate' for how to turn one one.+type EvilInvention a b = (TrappedAgent, a) -> b++-- | Combinator to turn a function into an 'EvilInvention'. Typically applied+-- via the '.' operator, like so:+--+-- >    incrementinator :: EvilInvention Int Int+-- >    incrementinator = (+1) . inator+inator :: (TrappedAgent, a) -> a+inator = snd++-- | /Warning:/ All 'EvilInvention's have a 'selfDestruct' ability. When an+-- 'EvilInvention' self-destructs, all effects of evil plans in the+-- 'TriStateArea' are nullified, as if 'Nothing' ever happened.+selfDestruct :: EvilInvention a b -> TriStateArea ()+selfDestruct _ = fail "Kaboom!"++++-- | Agents are secret, and distinguished only by their letter designations.+data Agent = Agent Char+    deriving (Eq, Ord, Bounded, Read, Show)++-- | 'Agent' @\'P\'@+perryThePlatypus :: Agent+perryThePlatypus = Agent 'P'++-- | When trapped, an 'Agent' enables an 'EvilInvention' to be 'activate'd and+-- then used. The scope of trapping an 'Agent' is strictly delimited.+-- See 'whileTrapping'.+data TrappedAgent = TrappedAgent Agent+++-- | Activation and operation of an 'EvilInvention' is strictly limited to the+-- 'TriStateArea'. Plans executed in the 'TriStateArea' may 'fail', causing the+-- whole plan to have no externally visible effect.+data TriStateArea a = TriStateArea { takeOver :: TrappedAgent -> Maybe a }+instance Functor TriStateArea where+    fmap = liftM+instance Monad TriStateArea where+    return = TriStateArea . const . Just+    f >>= g = TriStateArea (\ta -> takeOver f ta >>= flip takeOver ta . g)+    fail _ = TriStateArea $ const Nothing++-- | The 'Agent' trapped in the 'TriStateArea'.+trappedAgent :: TriStateArea TrappedAgent+trappedAgent = TriStateArea Just++-- | 'EvilInvention's must be activated before use. The activated machine can+-- then be applied to suitable targets of scorn and dislike. /N.B.:/ Activation+-- and subsequent operation of an 'EvilInvention' can only be performed in the+-- 'TriStateArea'.+--+-- > evilPlan :: TriStateArea Int+-- > evilPlan = do+-- >    zap <- activate incrementinator+-- >    as <- mapM zap [1..37]+-- >    b <- zap 38 -- I never really liked the number 38+-- >    selfDestruct incrementinator+-- >    cs <- mapM zap [39..100]+-- >    return $ sum as + b + sum cs+activate :: EvilInvention a b -> TriStateArea (a -> TriStateArea b)+activate contraption = return $ \a -> do+    ta <- trappedAgent+    return $ contraption (ta,a)++-- | To execute any plan (evil or 'otherwise') in the 'TriStateArea', an+-- 'Agent' must be trapped with this function, and held for the duration of+-- of the plan.+--+-- > executeEvilPlan = whileTrapping perryThePlatypus evilPlan+-- >+-- > main :: IO ()+-- > main = do+-- >     putStrLn $+-- >         case executeEvilPlan of+-- >             Nothing -> "Curse you, Perry the Platypus!"+-- >             Just a -> "Ha ha! I have incremented the TriStateArea to " ++ show a++whileTrapping :: Agent -> TriStateArea a -> Maybe a+whileTrapping a f = takeOver f $ TrappedAgent a
+ EvilPlan.hs view
@@ -0,0 +1,29 @@+-- | Run an evil plan to increment the Tri-State area with the incrementinator.++module Main (+    main+) where++import Acme.Inator++incrementinator :: EvilInvention Int Int+incrementinator = (+1) . inator++evilPlan :: TriStateArea Int+evilPlan = do+    zap <- activate incrementinator+    as <- mapM zap [1..37]+    b <- zap 38 -- I never really liked the number 38+    selfDestruct incrementinator+    cs <- mapM zap [39..100]+    return $ sum as + b + sum cs++executeEvilPlan :: Maybe Int+executeEvilPlan = whileTrapping perryThePlatypus evilPlan++main :: IO ()+main = do+    putStrLn $+        case executeEvilPlan of+            Nothing -> "Curse you, Perry the Platypus!"+            Just a -> "Aha! I have incremented the tri-state area to " ++ show a
+ Setup.lhs view
@@ -0,0 +1,6 @@+#!/usr/bin/runhaskell +> module Main where+> import Distribution.Simple+> main :: IO ()+> main = defaultMain+
+ acme-inator.cabal view
@@ -0,0 +1,22 @@+Name:            acme-inator+Version:         0.1.0.0+License:         PublicDomain+Author:          Mark Lentczner <mzero@glyphic.com>+Maintainer:      Mark Lentczner <mzero@glyphic.com>+Category:        Acme+Build-type:      Simple+Cabal-version:   >=1.8+Synopsis:        Evil inventions in the Tri-State area+Description:+    Construction and operation of evil inventions in the Tri-State area.+    Based on the pioneering work of Dr. Heinz Doofenshmirtz.++Library+  Exposed-modules: Acme.Inator+  Build-depends: base == 4.*+  Ghc-options: -fwarn-tabs -Wall++Executable evilplan+  Main-is: EvilPlan.hs+  Build-depends: base == 4.*+  Ghc-options: -fwarn-tabs -Wall