lgtk 0.2 → 0.3
raw patch · 10 files changed
+130/−57 lines, 10 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Control.MLens.NewRef: instance NewRef IO
- GUI.MLens.Gtk: mapI :: (Monad m, Functor m, Monad n, Functor n) => Morph n m -> Morph m n -> I m -> I n
- GUI.MLens.Gtk.IO: instance Monoid (IO ())
- GUI.MLens.Gtk.IO: runI :: I IO -> IO ()
- GUI.MLens.Gtk.Interface: Action :: (m (I m)) -> I m
- GUI.MLens.Gtk.Interface: Button :: Free m String -> Free m (Maybe (m ())) -> I m
- GUI.MLens.Gtk.Interface: Cell :: Bool -> m a -> (a -> I m) -> I m
- GUI.MLens.Gtk.Interface: Checkbox :: (Ref m Bool) -> I m
- GUI.MLens.Gtk.Interface: Combobox :: [String] -> (Ref m Int) -> I m
- GUI.MLens.Gtk.Interface: Entry :: (Ref m String) -> I m
- GUI.MLens.Gtk.Interface: Horizontal :: ListLayout
- GUI.MLens.Gtk.Interface: Label :: (Free m String) -> I m
- GUI.MLens.Gtk.Interface: List :: ListLayout -> [I m] -> I m
- GUI.MLens.Gtk.Interface: Notebook :: [(String, I m)] -> I m
- GUI.MLens.Gtk.Interface: Vertical :: ListLayout
- GUI.MLens.Gtk.Interface: action_ :: I m -> Free m (Maybe (m ()))
- GUI.MLens.Gtk.Interface: data I m
- GUI.MLens.Gtk.Interface: data ListLayout
- GUI.MLens.Gtk.Interface: dynamic_interface_ :: I m -> a -> I m
- GUI.MLens.Gtk.Interface: label_ :: I m -> Free m String
- GUI.MLens.Gtk.Interface: remember_content_ :: I m -> Bool
- GUI.MLens.Gtk.Interface: underlying_value_ :: I m -> m a
+ Control.MLens: (***) :: Monad m => MLens m a b -> MLens m c d -> MLens m (a, c) (b, d)
+ Control.MLens: (.) :: Category cat => forall b c a. cat b c -> cat a b -> cat a c
+ Control.MLens: class NewRef m => ExtRef m
+ Control.MLens: class Monad m => NewRef m
+ Control.MLens: data Ext i m a
+ Control.MLens: data MLens m a b
+ Control.MLens: extRef :: ExtRef m => Ref m b -> MLens m a b -> a -> m (Ref m a)
+ Control.MLens: forkLens :: (Monoid a, Monad m) => MLens m a (a, a)
+ Control.MLens: fromLens :: Monad m => Lens a b -> MLens m a b
+ Control.MLens: fstLens :: Monad m => MLens m (a, b) a
+ Control.MLens: getL :: Monad m => MLens m a b -> a -> m b
+ Control.MLens: id :: Category cat => forall a. cat a a
+ Control.MLens: ithLens :: Monad m => Int -> MLens m [a] a
+ Control.MLens: joinLens :: Monad m => MLens m a (MLens m a b) -> MLens m a b
+ Control.MLens: joinML :: Monad m => (a -> m (MLens m a b)) -> MLens m a b
+ Control.MLens: justLens :: Monad m => a -> MLens m (Maybe a) a
+ Control.MLens: lens :: Monad m => (a -> b) -> (b -> a -> a) -> MLens m a b
+ Control.MLens: listLens :: Monad m => MLens m (Bool, (a, [a])) [a]
+ Control.MLens: mapMLens :: (Monad m, Monad n) => Morph m n -> MLens m a b -> MLens n a b
+ Control.MLens: maybeLens :: Monad m => MLens m (Bool, a) (Maybe a)
+ Control.MLens: memoMLens :: (NewRef m, Eq a, Eq b) => MLens m a b -> m (MLens m a b)
+ Control.MLens: memoRead :: NewRef m => m a -> m (m a)
+ Control.MLens: memoWrite :: (NewRef m, Eq b) => (b -> m a) -> m (b -> m a)
+ Control.MLens: modL :: Monad m => MLens m b a -> (a -> a) -> b -> m b
+ Control.MLens: modRef :: Monad m => Ref m a -> (a -> a) -> m ()
+ Control.MLens: newRef :: NewRef m => a -> m (Ref m a)
+ Control.MLens: readRef :: Monad m => MLens m Unit a -> m a
+ Control.MLens: runExt :: Monad m => (forall i. Ext i m a) -> m a
+ Control.MLens: runExt_ :: (Functor m, NewRef m) => (forall n. (Monad n, Functor n) => Morph m n -> Morph n m -> c n -> c m) -> (forall i. c (Ext i m)) -> m (c m)
+ Control.MLens: setL :: Monad m => MLens m a b -> b -> a -> m a
+ Control.MLens: showLens :: (Monad m, Show a, Read a) => MLens m a String
+ Control.MLens: sndLens :: Monad m => MLens m (a, b) b
+ Control.MLens: toLens :: (forall m. Monad m => MLens m a b) -> Lens a b
+ Control.MLens: type Lens a b = MLens Identity a b
+ Control.MLens: type Morph m n = forall a. m a -> n a
+ Control.MLens: type Ref m a = MLens m Unit a
+ Control.MLens: undoTr :: ExtRef m => (a -> a -> Bool) -> Ref m a -> m (m (Maybe (m ())), m (Maybe (m ())))
+ Control.MLens: unitLens :: Monad m => MLens m a ()
+ Control.MLens: writeRef :: Monad m => Ref m a -> a -> m ()
+ Control.MLens.NewRef.Unsafe: instance NewRef IO
+ Data.MLens.Ref: data Unit
+ Data.MLens.Ref: instance Eq Unit
+ Data.MLens.Ref: instance Show Unit
+ GUI.MLens.Gtk: Action :: (m (I m)) -> I m
+ GUI.MLens.Gtk: Button :: Free m String -> Free m (Maybe (m ())) -> I m
+ GUI.MLens.Gtk: Cell :: Bool -> m a -> (a -> I m) -> I m
+ GUI.MLens.Gtk: Checkbox :: (Ref m Bool) -> I m
+ GUI.MLens.Gtk: Combobox :: [String] -> (Ref m Int) -> I m
+ GUI.MLens.Gtk: Entry :: (Ref m String) -> I m
+ GUI.MLens.Gtk: Horizontal :: ListLayout
+ GUI.MLens.Gtk: Label :: (Free m String) -> I m
+ GUI.MLens.Gtk: List :: ListLayout -> [I m] -> I m
+ GUI.MLens.Gtk: Notebook :: [(String, I m)] -> I m
+ GUI.MLens.Gtk: Vertical :: ListLayout
+ GUI.MLens.Gtk: action_ :: I m -> Free m (Maybe (m ()))
+ GUI.MLens.Gtk: data I m
+ GUI.MLens.Gtk: data ListLayout
+ GUI.MLens.Gtk: dynamic_interface_ :: I m -> a -> I m
+ GUI.MLens.Gtk: label_ :: I m -> Free m String
+ GUI.MLens.Gtk: remember_content_ :: I m -> Bool
+ GUI.MLens.Gtk: underlying_value_ :: I m -> m a
- Data.MLens.Ref: readRef :: Monad m => MLens m () a -> m a
+ Data.MLens.Ref: readRef :: Monad m => MLens m Unit a -> m a
- Data.MLens.Ref: type Ref m a = MLens m () a
+ Data.MLens.Ref: type Ref m a = MLens m Unit a
- GUI.MLens.Gtk: smartButton :: (Eq a, Monad m, Functor m) => Free m String -> (a -> m a) -> MLens m () a -> I m
+ GUI.MLens.Gtk: smartButton :: (Eq a, Monad m, Functor m) => Free m String -> (a -> m a) -> Ref m a -> I m
Files
- lgtk.cabal +10/−6
- main/Main.hs +2/−3
- src/Control/MLens.hs +56/−0
- src/Control/MLens/ExtRef/Pure.hs +4/−4
- src/Control/MLens/NewRef.hs +0/−10
- src/Control/MLens/NewRef/Unsafe.hs +19/−0
- src/Data/MLens.hs +1/−0
- src/Data/MLens/Ref.hs +23/−14
- src/GUI/MLens/Gtk.hs +13/−18
- src/GUI/MLens/Gtk/IO.hs +2/−2
lgtk.cabal view
@@ -1,15 +1,16 @@ name: lgtk-version: 0.2+version: 0.3 category: GUI synopsis: lens-based GUI with Gtk backend description:- Try the demo executable lgtkdemo and read the source.+ The main interface of LGtk is "GUI.MLens.Gtk". .- See also <http://people.inf.elte.hu/divip/LGtk.html>-stability: alpha+ See also <http://people.inf.elte.hu/divip/LGtk/index.html>+stability: experimental license: BSD3 license-file: LICENSE author: Péter Diviánszky+homepage: http://people.inf.elte.hu/divip/LGtk/index.html maintainer: divipp@gmail.com cabal-version: >= 1.8 build-type: Simple@@ -33,19 +34,22 @@ Data.MLens.Ref Control.MLens.NewRef+ Control.MLens.NewRef.Unsafe Control.MLens.ExtRef Control.MLens.ExtRef.Test Control.MLens.ExtRef.Pure Control.MLens.ExtRef.Pure.Test+ Control.MLens - GUI.MLens.Gtk.Interface- GUI.MLens.Gtk.IO GUI.MLens.Gtk GUI.MLens.Gtk.ADTEditor GUI.MLens.Gtk.Demos.Tri GUI.MLens.Gtk.Demos.IntListEditor GUI.MLens.Gtk.Demos.TEditor+ other-modules:+ GUI.MLens.Gtk.IO+ GUI.MLens.Gtk.Interface ghc-options: -Wall -fno-warn-incomplete-patterns
main/Main.hs view
@@ -1,8 +1,7 @@-{-# LANGUAGE RankNTypes #-} import Control.Monad import Control.Monad.Trans-import Prelude hiding ((.), id) +import Data.MLens.Ref (fileRef) import GUI.MLens.Gtk import GUI.MLens.Gtk.Demos.Tri@@ -11,7 +10,7 @@ {- |-We use @unsafeRunI@ only because we read from an write to a file.+We use @unsafeRunI@ only because we read from and write to a file. It is considered unsafe usage, because the system do not guarantee that only this program acesses the files at runtime. -}
+ src/Control/MLens.hs view
@@ -0,0 +1,56 @@+-- {-# LANGUAGE ExistentialQuantification #-}+-- {-# LANGUAGE RankNTypes #-}+-- | The main monadic lens interface, ideally users should import only this module.+module Control.MLens+ ( -- * Data types+ MLens+ , Lens+ , Ref++ -- * Lens operations+ , getL, setL, modL++ -- * Lens transformations+ , fromLens, toLens+ , mapMLens+ , (.)+ , (***)+ , joinML, joinLens+ , memoMLens++ -- * Pure lenses+ , id+ , unitLens+ , fstLens, sndLens+ , maybeLens+ , listLens+ , ithLens++ -- * Impure lenses+ , lens+ , forkLens+ , justLens+ , showLens++ -- * Reference operations+ , readRef, writeRef, modRef+ , NewRef (..)+ , ExtRef (..)+ , Ext, runExt, runExt_+ , undoTr++ -- * Auxiliary definitions+ , Morph+ , memoRead+ , memoWrite+ ) where++import Control.Category+import Prelude hiding ((.), id)++import Data.MLens+import Data.MLens.Ref+import Control.MLens.ExtRef+import Control.MLens.ExtRef.Pure++
src/Control/MLens/ExtRef/Pure.hs view
@@ -70,7 +70,7 @@ instance MonadTrans (Ext i) where lift = Ext . lift -extRef_ :: Monad m => MLens (Ext i m) a x -> MLens (Ext i m) a x -> a -> Ext i m (Ref (Ext i m) a)+extRef_ :: Monad m => Ref (Ext i m) x -> MLens (Ext i m) a x -> a -> Ext i m (Ref (Ext i m) a) extRef_ r1 r2 a0 = Ext $ do a1 <- g a0 (t,z) <- state $ extend_ (runStateT . f) (runStateT . g) a1@@ -79,14 +79,14 @@ , \a -> Ext $ (StateT $ liftM ((,) ()) . z a) >> return c ) where- f b = unExt $ getL r2 b >>= flip (setL r1) b- g b = unExt $ getL r1 b >>= flip (setL r2) b+ f a = unExt $ getL r2 a >>= \x -> writeRef r1 x >> return a+ g b = unExt $ readRef r1 >>= flip (setL r2) b instance (Monad m) => NewRef (Ext i m) where newRef = extRef_ unitLens unitLens instance (Monad m) => ExtRef (Ext i m) where- extRef = extRef_ . (. unitLens)+ extRef = extRef_ -- | Basic running of the @(Ext i m)@ monad. runExt :: Monad m => (forall i . Ext i m a) -> m a
src/Control/MLens/NewRef.hs view
@@ -10,10 +10,8 @@ , memoRead, memoWrite ) where -import Data.IORef import Control.Monad import Control.Monad.Writer-import Prelude -- hiding ((.), id) import Data.MLens import Data.MLens.Ref@@ -25,14 +23,6 @@ -} class (Monad m) => NewRef m where newRef :: a -> m (Ref m a)---- | Note that this instance does not fulfil the @NewRef@ laws in a multi-threaded environment.-instance NewRef IO where- newRef x = do- r <- newIORef x- return $ MLens $ \() -> do- x <- readIORef r- return (x, writeIORef r) instance (NewRef m, Monoid w) => NewRef (WriterT w m) where newRef = liftM (mapMLens lift) . lift . newRef
+ src/Control/MLens/NewRef/Unsafe.hs view
@@ -0,0 +1,19 @@+{-# LANGUAGE RankNTypes #-}+-- | This module export only the @NewRef@ instance for @IO@ which does not fulfil the @NewRef@ laws in a multi-threaded environment.+module Control.MLens.NewRef.Unsafe+ () where++import Data.IORef++import Data.MLens+import Control.MLens.NewRef++-- | Note that this instance does not fulfil the @NewRef@ laws in a multi-threaded environment.+instance NewRef IO where+ newRef x = do+ r <- newIORef x+ return $ MLens $ \unit -> do+ x <- readIORef r+ return (x, \y -> writeIORef r y >> return unit)++
src/Data/MLens.hs view
@@ -97,6 +97,7 @@ toLens :: (forall m . Monad m => MLens m a b) -> Lens a b toLens k = k +-- | Impure (but effect-free) lens constuctor lens :: Monad m => (a -> b) -> (b -> a -> a) -> MLens m a b lens get set = MLens $ \a -> return (get a, return . flip set a)
src/Data/MLens/Ref.hs view
@@ -1,8 +1,10 @@ {-# LANGUAGE RankNTypes #-} module Data.MLens.Ref- ( -- * Data type for reference lenses- Ref+ ( Unit + -- * Data type for reference lenses+ , Ref+ -- * Reference operations , readRef, writeRef, modRef @@ -21,6 +23,13 @@ import Data.MLens +{- | +The abstract data type @Unit@ is isomorphic to @()@,+but by making it abstract we can prevent using references+on the left hand side of lens composition.+-}+data Unit = Unit deriving (Eq, Show)+ {- | Note that references lenses can be composed with lenses. For example, if@@ -33,7 +42,7 @@ Reference laws for pure references: - * @(readRef r)@ has no side effect+ * @(readRef r >> return ())@ === @(return ())@ * @(readRef r >>= writeRef r)@ === @(return ())@ @@ -41,21 +50,18 @@ * @(writeRef r a >> writeRef r a')@ === @(writeRef r a')@ - * Reference laws need not be preserved by composition, but they should be preserved if a- pure lens is composed from the left.--These first four laws are equivalent to the get-no-effect, set-get, get-set and set-set laws for monadic lenses.+These laws are equivalent to the get-no-effect, set-get, get-set and set-set laws for monadic lenses. -}-type Ref m a = MLens m () a+type Ref m a = MLens m Unit a -readRef :: Monad m => MLens m () a -> m a-readRef k = getL k ()+readRef :: Monad m => MLens m Unit a -> m a+readRef k = getL k Unit writeRef :: Monad m => Ref m a -> a -> m ()-writeRef r a = setL r a ()+writeRef r a = setL r a Unit >> return () modRef :: Monad m => Ref m a -> (a -> a) -> m ()-k `modRef` f = modL k f ()+k `modRef` f = modL k f Unit >> return () -- | Using @fileRef@ is safe if the file is not used concurrently. fileRef :: FilePath -> IO (Ref IO String)@@ -63,13 +69,16 @@ -- | Note that if you write @Nothing@, the file is deleted. fileRef_ :: FilePath -> IO (Ref IO (Maybe String))-fileRef_ f = return $ MLens $ \() -> do+fileRef_ f = return $ MLens $ \Unit -> do b <- doesFileExist f if b then do xs <- readFile f length xs `seq` return (Just xs, wr) else return (Nothing, wr)- where wr = maybe (doesFileExist f >>= \b -> when b (removeFile f)) (writeFile f)+ where+ wr mb = do+ maybe (doesFileExist f >>= \b -> when b (removeFile f)) (writeFile f) mb+ return Unit logMLens :: Monad m => (a -> m ()) -> (a -> m ()) -> MLens m a a logMLens getLog setLog = MLens $ \a -> getLog a >> return (a, \b -> setLog b >> return b)
src/GUI/MLens/Gtk.hs view
@@ -2,22 +2,20 @@ {-# LANGUAGE RankNTypes #-} -- | The main LGtk interface, ideally users should import only this module. module GUI.MLens.Gtk- ( module Control.Category- , module Data.MLens- , module Data.MLens.Ref- , module Control.MLens.ExtRef- , module GUI.MLens.Gtk.Interface-- -- * Running (rendering) and interface description- , runI- , unsafeRunI+ ( -- * Lenses and references+ module Control.MLens - -- * Composed+ -- * GUI combinators+ , I (..)+ , ListLayout (..) , vcat, hcat , smartButton + -- * Running GUI descriptions+ , runI+ , unsafeRunI+ -- * Auxiliary functions- , mapI , toFree ) where @@ -25,11 +23,8 @@ import Control.Monad.Free import Prelude hiding ((.), id) -import Data.MLens-import Data.MLens.Ref-import Control.MLens.ExtRef+import Control.MLens import GUI.MLens.Gtk.Interface-import Control.MLens.ExtRef.Pure import qualified GUI.MLens.Gtk.IO as Gtk vcat :: [I m] -> I m@@ -40,16 +35,16 @@ smartButton :: (Eq a, Monad m, Functor m) =>- Free m String -> (a -> m a) -> MLens m () a -> I m+ Free m String -> (a -> m a) -> Ref m a -> I m smartButton s f k = Button s $ toFree $ readRef k >>= \x -> f x >>= \y -> if y == x then return Nothing else return $ Just ((readRef k >>= f) >>= writeRef k) --- | Run (render) and interface description+-- | Run an interface description runI :: (forall m . (Functor m, ExtRef m) => I m) -> IO () runI e = runExt_ mapI e >>= Gtk.runI --- | Run (render) and interface description+-- | Run an interface description -- -- Unsafe only if you do nasty things in the @IO@ monad, like forking threads unsafeRunI :: (forall i . I (Ext i IO)) -> IO ()
src/GUI/MLens/Gtk/IO.hs view
@@ -12,8 +12,8 @@ import Graphics.UI.Gtk -import Data.MLens.Ref-import Control.MLens.NewRef+import Control.MLens+import Control.MLens.NewRef.Unsafe () import GUI.MLens.Gtk.Interface ------------------