This may too biased to be useful to others but in case you have similar sensibilities, the above github link may make your life easier if you want to play around with Haskell.
It will only work on Ubuntu 13.10 (Saucy) and you'll need to understand rake/ruby to make it work for you.
If you have any problems, please email me at my github account.submitted by slacket
[link] [3 comments]
Given that cabal updates almost every day with new packages, I feel that it would be pretty awesome if a cabal-daemon were developed. I often forget to 'cabal update' before performing installs.
Said daemon would poll hackage for package update notifications, and update the local cabal package index with any changes. Being a daemon, it would run as a low-priority process in the background. I imagine said daemon polling once every 15-30 minutes is more than enough, though a push-based design might be even better.
Thoughts?submitted by alejcabrera
[link] [7 comments]
When I recently wrote about porting my haskell-testing-stub project to tasty I mentioned that test-framework still has more libraries than tasty. I decided to contribute to changing that and released two small packages that extend tasty with extra functionality:
- tasty-hunit-adapter allows to import existing HUnit tests into tasty (hackage, github): module Main where import Test.HUnit ( (~:), (@=?) ) import Test.Tasty ( defaultMain, testGroup ) import Test.Tasty.HUnit.Adapter ( hUnitTestToTestTree ) main :: IO () main = defaultMain $ testGroup "Migrated from HUnit" $ hUnitTestToTestTree ("HUnit test" ~: 2 + 2 @=? 4)
- tasty-program allows to run external program and test whether it terminates successfully (hackage, github): module Main ( main ) where import Test.Tasty import Test.Tasty.Program main :: IO () main = defaultMain $ testGroup "Compilation with GHC" $ [ testProgram "Foo" "ghc" ["-fforce-recomp", "foo.hs"] Nothing ]
This package has only this basic functionality at the moment. A missing feature is the possibility of logging stdout and stderr to a file so that it can later be inspected or perhaps used by a golden test (but for the latter tasty needs test dependencies).
A few months ago, Petr Pudlák kicked off the conduit-extra package with the addition of ZipSink. As a refresher, ZipSink provides an alternative Applicative instance for Sink which allows multiple Sinks to consume the same stream.
I've just release version 1.0.13 of conduit which promotes ZipSink from conduit-extra into conduit itself. This abstraction has proven to be generally useful, and I hope others enjoy it as well. If you want a more in-depth review of it, please see the original blog post. The only change since then is renaming broadcast to sequenceSinks.
Along with this change, version 1.0.13 adds a new, similar concept: ZipSource and sequenceSources. The idea here is to combine together multiple streams, instead of sequencing one stream after another.
As a simple motivating example, let's say we have some files on the filesystem, where each file contains a list of student test scores. We want to combine together the test scores for all students for each of the tests. The following program does the job:import Control.Monad.Trans.Class (lift) import qualified Data.ByteString.Char8 as S8 import Data.Conduit import qualified Data.Conduit.Binary as CB import qualified Data.Conduit.List as CL import qualified Data.Map as Map type Name = String people :: [Name] people = words "alice bob charlie" files :: Map.Map Name FilePath files = Map.fromList $ map (\name -> (name, name ++ ".txt")) people scores :: MonadResource m => FilePath -> Source m Int scores fp = CB.sourceFile fp $= CB.lines $= CL.map (read . S8.unpack) sources :: MonadResource m => Map.Map Name (Source m Int) sources = fmap scores files sources' :: MonadResource m => Source m (Map.Map Name Int) sources' = sequenceSources sources main :: IO () main = runResourceT $ sources' $$ CL.mapM_ (lift . print)
The important bit is the definition of sources'. We use sequenceSources to combine together each of the individual test scores into a single test score map. With some basic input files, the output looks like:fromList [("alice",1),("bob",3),("charlie",2)] fromList [("alice",2),("bob",2),("charlie",2)] fromList [("alice",3),("bob",1),("charlie",2)]