packages feed

keera-hails-reactivevalues 0.2.0.0 → 0.2.0.1

raw patch · 5 files changed

+264/−17 lines, 5 filesdep +HUnitdep +QuickCheckdep +directoryPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: HUnit, QuickCheck, directory, filepath, hlint, keera-hails-reactivevalues, mtl, process, regex-posix, tasty, tasty-hunit, tasty-quickcheck

API changes (from Hackage documentation)

- Control.GFunctor: instance Functor a => GFunctor a (->)
- Data.ReactiveValue: instance (Functor m, Monad m) => Functor (ReactiveFieldRead m)
- Data.ReactiveValue: instance Monad m => Contravariant (ReactiveFieldWrite m)
- Data.ReactiveValue: instance Monad m => GFunctor (ReactiveFieldReadWrite m) BijectiveFunc
- Data.ReactiveValue: instance ReactiveValueRead (ReactiveFieldRead m a) a m
- Data.ReactiveValue: instance ReactiveValueRead (ReactiveFieldReadWrite m a) a m
- Data.ReactiveValue: instance ReactiveValueReadWrite (ReactiveFieldReadWrite m a) a m
- Data.ReactiveValue: instance ReactiveValueWrite (ReactiveFieldReadWrite m a) a m
- Data.ReactiveValue: instance ReactiveValueWrite (ReactiveFieldWrite m a) a m
- Data.ReactiveValue: unBijectiveFunc :: BijectiveFunc a b -> (a -> b, b -> a)
+ Control.GFunctor: instance GHC.Base.Functor a => Control.GFunctor.GFunctor a (->)
+ Data.ReactiveValue: [unBijectiveFunc] :: BijectiveFunc a b -> (a -> b, b -> a)
+ Data.ReactiveValue: instance (GHC.Base.Functor m, GHC.Base.Monad m) => GHC.Base.Functor (Data.ReactiveValue.ReactiveFieldRead m)
+ Data.ReactiveValue: instance Data.ReactiveValue.ReactiveValueRead (Data.ReactiveValue.ReactiveFieldRead m a) a m
+ Data.ReactiveValue: instance Data.ReactiveValue.ReactiveValueRead (Data.ReactiveValue.ReactiveFieldReadWrite m a) a m
+ Data.ReactiveValue: instance Data.ReactiveValue.ReactiveValueReadWrite (Data.ReactiveValue.ReactiveFieldReadWrite m a) a m
+ Data.ReactiveValue: instance Data.ReactiveValue.ReactiveValueWrite (Data.ReactiveValue.ReactiveFieldReadWrite m a) a m
+ Data.ReactiveValue: instance Data.ReactiveValue.ReactiveValueWrite (Data.ReactiveValue.ReactiveFieldWrite m a) a m
+ Data.ReactiveValue: instance GHC.Base.Monad m => Control.GFunctor.GFunctor (Data.ReactiveValue.ReactiveFieldReadWrite m) Data.ReactiveValue.BijectiveFunc
+ Data.ReactiveValue: instance GHC.Base.Monad m => Data.Functor.Contravariant.Contravariant (Data.ReactiveValue.ReactiveFieldWrite m)

Files

keera-hails-reactivevalues.cabal view
@@ -7,13 +7,18 @@ -- The package version. See the Haskell package versioning policy -- (http://www.haskell.org/haskellwiki/Package_versioning_policy) for -- standards guiding when and how versions should be incremented.-Version:             0.2.0.0+Version:             0.2.0.1  -- A short (one-line) description of the package. Synopsis:            Haskell on Rails - Reactive Values  -- A longer description of the package.--- Description:         +Description:+  This package contains a general definition of Reactive Values and several useful combinators. A reactive value is a /typed mutable value with access properties and change propagation/. Access property can be read-only, read-write or read-write.+  .+  How an RV is actually implemented, and when and how change propagation is executed is dependent on each RV. For instance, Gtk widget properties would normally use the standard event-handler installers to implement change propagation, whereas pure Haskell values might fork a thread (or not) and propagate changes asynchronously.+  .+  RVs can be created from pure models (see <https://github.com/keera-studios/keera-hails/tree/master/keera-hails-mvc-model-lightmodel keera-hails-mvc-model-lightmodel> and  <https://github.com/keera-studios/keera-hails/tree/master/keera-hails-mvc-model-protectedmodel keera-hails-mvc-model-protectedmodel>), Gtk+/WX/Qt/HTML DOM/Android widget properties/event handlers/getters/setters, files, sockets, FRP networks. Other backends are also available. See <https://github.com/keera-studios/keera-hails keera-hails> for a list of available backends, tutorials, etc.  -- URL for the project homepage or repository. Homepage:            http://www.keera.es/blog/community/@@ -32,7 +37,7 @@ Maintainer:          ivan.perez@keera.es  -- A copyright notice.--- Copyright:           +-- Copyright:  Category:            Development @@ -40,20 +45,88 @@  -- Extra files to be distributed with the package, such as examples or -- a README.--- Extra-source-files:  +-- Extra-source-files:  -- Constraint on the version of Cabal needed to build this package.-Cabal-version:       >=1.2+Cabal-version:       >=1.8 +-- You can disable the hlint test suite with -f-test-hlint+flag test-hlint+  default: True+  manual: True +-- You can disable the haddock coverage test suite with -f-test-doc-coverage+flag test-doc-coverage+  default: True+  manual: True++-- You can disable the haddock coverage test suite with -f-test-unit-tests+flag test-unit-tests+  default: True+  manual: True+ Library   hs-source-dirs: src/-  +   ghc-options: -Wall -fno-warn-unused-do-bind -O2    -- Modules exported by the library.   Exposed-modules: Data.ReactiveValue                    Control.GFunctor-  +   -- Packages needed in order to build this package.   Build-depends: base >= 4 && < 5, contravariant++-- Verify that the code follows reasonable coding standards+test-suite hlint+  type: exitcode-stdio-1.0+  main-is: hlint.hs+  ghc-options: -w -threaded -rtsopts -with-rtsopts=-N+  hs-source-dirs: tests++  if !flag(test-hlint)+    buildable: False+  else+    build-depends:+      base >= 4 && < 5,+      hlint >= 1.7++-- Verify that the code is thoroughly documented+test-suite haddock-coverage+  type: exitcode-stdio-1.0+  main-is: HaddockCoverage.hs+  ghc-options: -Wall+  hs-source-dirs: tests++  if !flag(test-doc-coverage)+    buildable: False+  else+    build-depends:+      base >= 4 && < 5,+      directory,+      filepath,+      process,+      regex-posix++-- Verify that the code is thoroughly documented+test-suite unit-tests+  type: exitcode-stdio-1.0+  main-is: Tasty.hs+  ghc-options: -Wall+  hs-source-dirs: tests++  if !flag(test-unit-tests)+    buildable: False+  else+    build-depends:+      base >= 4 && < 5,+      -- This library and testing deps+      mtl,+      keera-hails-reactivevalues,++      -- Testing libraries+      tasty,+      tasty-quickcheck,+      tasty-hunit,+      QuickCheck,+      HUnit
src/Data/ReactiveValue.hs view
@@ -241,7 +241,7 @@  -- | Wrap a monadic computation in a writable reactive value. wrapMW :: (a -> m ()) -> ReactiveFieldWrite m a-wrapMW f = ReactiveFieldWrite f+wrapMW = ReactiveFieldWrite  -- | Wrap a monadic computation in a writable reactive value. -- It discards the written value and executes the operation.@@ -250,15 +250,16 @@ -- polymorphic in the value that may be written to it. Using -- 'wrapDo_' may save you some extra type signatures. wrapDo :: m () -> ReactiveFieldWrite m a-wrapDo f = wrapMW (const f)+wrapDo = wrapMW . const  -- | Wrap a monadic computation in a writable reactive value of type -- unit. It discards the written value and executes the operation. wrapDo_ :: m () -> ReactiveFieldWrite m ()-wrapDo_ f = wrapMW (\() -> f)+wrapDo_ = wrapDo  -- *** Lifting (source) computations into readable RVs. +{-# ANN wrapMR "HLint: ignore Eta reduce" #-} -- | Wrap an reading operation and an notification installer in -- a readable reactive value. wrapMR :: m a -> (m () -> m ()) -> ReactiveFieldRead m a@@ -270,6 +271,7 @@ wrapMRPassive :: Monad m => m a -> ReactiveFieldRead m a wrapMRPassive f = ReactiveFieldRead f (const (return ())) +{-# ANN eventR "HLint: ignore Eta reduce" #-} -- | Wrap event-handler installers in RVs eventR :: Monad m => (m () -> m ()) -> ReactiveFieldRead m () eventR notifInstaller = ReactiveFieldRead (return ()) notifInstaller@@ -283,9 +285,11 @@ bijection :: (a -> b, b -> a) -> BijectiveFunc a b bijection = BijectiveFunc +{-# ANN direct "HLint: ignore Redundant bracket" #-} direct :: BijectiveFunc a b -> (a -> b) direct = fst . unBijectiveFunc +{-# ANN inverse "HLint: ignore Redundant bracket" #-} inverse :: BijectiveFunc a b -> (b -> a) inverse = snd . unBijectiveFunc @@ -309,8 +313,9 @@ pairRW :: (Monad m,            ReactiveValueReadWrite a b m,            ReactiveValueReadWrite c d m)-       => a -> c -> ReactiveFieldReadWrite m (b, d)-pairRW a b = liftRW2 (bijection (id, id)) a b+       => a -> c+       -> ReactiveFieldReadWrite m (b, d)+pairRW = liftRW2 (bijection (id, id))  {-# INLINE eqCheck #-} eqCheck :: (Eq v, Monad m) => ReactiveFieldReadWrite m v -> ReactiveFieldReadWrite m v@@ -333,6 +338,7 @@  -- * Merging +{-# ANN lMerge "HLint: ignore Use const" #-} -- | Left merge (give priority to the value on the left) lMerge :: (Monad m, ReactiveValueRead a v m, ReactiveValueRead b v m)        => a -> b -> ReactiveFieldRead m v@@ -379,8 +385,8 @@       => c -> v       -> ReactiveFieldReadWrite m a ifRW_ c r = ReactiveFieldReadWrite setter getter notifier-  where setter x   = reactiveValueWrite r x-        getter     = reactiveValueRead r+  where setter = reactiveValueWrite r+        getter = reactiveValueRead r         -- If either changes, the value *may* be propagated         notifier p = do reactiveValueOnCanRead c (when' p)                         reactiveValueOnCanRead r (when' p)@@ -411,9 +417,9 @@         => c         -> ReactiveFieldRead m Bool guardRO c = ReactiveFieldRead getter notifier-  where getter     = reactiveValueRead c+  where getter   = reactiveValueRead c         -- If either changes, the value *may* be propagated-        notifier p = reactiveValueOnCanRead c (when' p)+        notifier = reactiveValueOnCanRead c . when'          -- Propagate only if the condition holds          where when' m = do x <- reactiveValueRead c@@ -425,7 +431,7 @@          -> (a -> Bool)          -> ReactiveFieldRead m a guardRO' c p = ReactiveFieldRead getter notifier-  where getter     = reactiveValueRead c+  where getter   = reactiveValueRead c         -- If either changes, the value *may* be propagated         notifier = reactiveValueOnCanRead c . when' 
+ tests/HaddockCoverage.hs view
@@ -0,0 +1,94 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  Main (HaddockCoverage)+-- Copyright   :  (C) 2015 Ivan Perez+-- License     :  BSD-style (see the file LICENSE)+-- Maintainer  :  Ivan Perez <ivan.perez@keera.co.uk>+-- Stability   :  provisional+-- Portability :  portable+--+-- Copyright notice: This file borrows code +-- https://hackage.haskell.org/package/lens-4.7/src/tests/doctests.hsc+-- which is itself licensed BSD-style as well.+--+-- Run haddock on a source tree and report if anything in any+-- module is not documented.+-----------------------------------------------------------------------------+module Main where++import Control.Monad+import Data.List+import System.Directory+import System.Exit+import System.FilePath+import System.IO+import System.Process+import Text.Regex.Posix++main :: IO ()+main = do+  -- Find haskell modules+  -- TODO: Ideally cabal should do this (provide us with the+  -- list of modules). An alternative would be to use cabal haddock+  -- but that would need a --no-html argument or something like that.+  -- Alternatively, we could use cabal haddock with additional arguments.+  --+  -- See:+  -- https://github.com/keera-studios/haddock/commit/d5d752943c4e5c6c9ffcdde4dc136fcee967c495+  -- https://github.com/haskell/haddock/issues/309#issuecomment-150811929+  files <- getSources++  -- Run haddock in the right sandbox.+  -- NOTE: you need this version of haddock:+  -- https://github.com/keera-studios/haddock/+  --+  -- TODO: adapt to use even the old version of haddock if the modified one is+  -- not present. We can test with haddock --csv-coverage and no input+  -- and check the exit code.+  let haddockArgs = [ "--csv-coverage", "--no-warnings" ] ++ files+  let cabalArgs   = [ "exec", "--", "haddock" ] ++ haddockArgs+  (code, out, _err) <- readProcessWithExitCode "cabal" cabalArgs ""++  -- Filter out coverage lines, and find those that denote undocumented+  -- modules.+  --+  -- TODO: is there a way to annotate a function as self-documenting,+  -- in the same way we do with ANN for hlint?+  let isIncompleteModule :: String -> Bool+      isIncompleteModule line = isCoverageLine line && not (line =~ "^ *100%")+        where isCoverageLine :: String -> Bool+              isCoverageLine line = line =~ "^ *[0-9]+%"++  let incompleteModules :: [String]+      incompleteModules = filter isIncompleteModule $ lines out++  -- Based on the result of haddock, report errors and exit.+  -- Note that, unline haddock, this script does not+  -- output anything to stdout. It uses stderr instead+  -- (as it should).+  case (code, incompleteModules) of+    (ExitSuccess  , []) -> return ()+    (ExitFailure _, _)  -> exitFailure+    (_            , _)  -> do+      hPutStrLn stderr "The following modules are not fully documented:"+      mapM_ (hPutStrLn stderr) incompleteModules+      exitFailure++getSources :: IO [FilePath]+getSources = filter isHaskellFile <$> go "src"+  where+    go dir = do+      (dirs, files) <- getFilesAndDirectories dir+      (files ++) . concat <$> mapM go dirs++    isHaskellFile fp = isSuffixOf ".hs" fp || isSuffixOf ".lhs" fp++getFilesAndDirectories :: FilePath -> IO ([FilePath], [FilePath])+getFilesAndDirectories dir = do+  c <- map (dir </>) . filter (`notElem` ["..", "."]) <$> getDirectoryContents dir+  (,) <$> filterM doesDirectoryExist c <*> filterM doesFileExist c++-- find-based implementation (not portable)+--+-- getSources :: IO [FilePath]+-- getSources = fmap lines $ readProcess "find" ["src/", "-iname", "*hs"] "" 
+ tests/Tasty.hs view
@@ -0,0 +1,51 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  Main (Tasty)+-- Copyright   :  (C) 2015 Ivan Perez+-- License     :  BSD-style (see the file LICENSE)+-- Maintainer  :  Ivan Perez <ivan.perez@keera.co.uk>+-- Stability   :  provisional+-- Portability :  portable+--+-- Test reactive value laws using Quickcheck/HUnit/Tasty. +--+-- See the following links for instructions and documentation:+--   https://github.com/feuerbach/tasty+--   https://ocharles.org.uk/blog/posts/2013-12-03-24-days-of-hackage-tasty.html+-----------------------------------------------------------------------------++-- Testing libraries+import Test.Tasty+import Test.Tasty.QuickCheck+-- import Test.QuickCheck+-- import Test.Tasty.HUnit++-- Tested libraries+import Control.Monad.Identity+import Data.ReactiveValue++main :: IO ()+main = defaultMain $+  testGroup "ReactiveValues"+    [ testGroup "GetSetLaws"+        [ testProperty "Getting after constant initialisation" getOnConst+        ]+    ]++-- * Reactive Value laws++-- ** Reactive Value get/set laws++-- | Check that constR returns the value put in.+getOnConst :: Int -> Bool+getOnConst = +  \val -> let rv   = constR (val :: Int)+              val' = runIdentity (reactiveValueRead rv)+          in val == val'++-- NOTE: To check that the testing system and the integration with cabal are+-- both working fine, you can use include this property in one of the tested+-- groups; the test suite should fail.+-- falseProperty = +--   testProperty "False" $+--     \val -> not (val == (val :: Int))
+ tests/hlint.hs view
@@ -0,0 +1,23 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  Main (hlint)+-- Copyright   :  (C) 2015 Ivan Perez, 2013-2014 Edward Kmett+-- License     :  BSD-style (see the file LICENSE)+-- Maintainer  :  Ivan Perez <ivan.perez@keera.co.uk>+-- Stability   :  provisional+-- Portability :  portable+--+-- This module runs HLint on the source tree.+-----------------------------------------------------------------------------+module Main where++import Control.Monad+import Language.Haskell.HLint+import System.Environment+import System.Exit++main :: IO ()+main = do+  args  <- getArgs+  hints <- hlint $ ["src"] ++ args+  unless (null hints) exitFailure