News aggregator

libiconv trouble?

General haskell list - Sat, 08/15/2015 - 9:26pm
Anyone else hit this, after updating to the new Haskell Platform? Davids-MacBook-Air-2:tmp dbanas$ ghci GHCi, version 7.10.2: :? for help <command line>: can't load .so/.DLL for: libiconv.dylib (dlopen(libiconv.dylib, 5): image not found) Thanks, -db _______________________________________________ Haskell mailing list Haskell< at >
Categories: Incoming News

Redundant entries in .cabal file?

General haskell list - Sat, 08/15/2015 - 4:03pm
Hi all, Does anyone know why I’m getting redundant entries in my ‘cabal init’ generated .cabal file: library exposed-modules: Language.Broker, Language.Broker ? Is it because I’m using a *.hsc file, as my source, and cabal is finding both files: Broker.hsc, and Broker.hs in the Language directory? Thanks, -db _______________________________________________ Haskell mailing list Haskell< at >
Categories: Incoming News

Neil Mitchell: Testing is never enough

Planet Haskell - Sat, 08/15/2015 - 3:40pm

Summary: Testing shows the presence, not the absence of bugs.

Recently, someone suggested to me that, thanks to test suites, things like changing compiler version or versions of library dependencies was "no big deal". If dependency changes still result in a passing test suite, then they have caused no harm. I disagree, and fortunately for me, Dijkstra explains it far more eloquently than I ever could:

Testing shows the presence, not the absence of bugs. Dijkstra (1969)

While a test suite can give you confidence in changes you make, it does not provide guarantees. Below are just a few reasons why.

The test suite does not cover all the code

For any reasonably sized code base (> 100 lines), covering all the lines of code is difficult. There are a number of factors that mean that mean a test suite is unlikely to provide 100% coverage:

  • Producing tests is a resource intensive activity, and most projects do not have the necessary manpower to test everything.
  • Sometimes there is no good way to test simple sugar functions - the definition is a specification of what the function should do.
  • Testing corner cases is difficult. As the corners get more obscure, the difficulty increases.
  • Testing error conditions is even harder. Some errors conditions have code to deal with them, but are believed to be unreachable.

The test suite does not cover all the ways through the code

Assuming the test suite really does cover every line of the code, making it cover every path through the code is almost certainly computationally infeasible. Consider a program taking a handful of boolean options. While it might be feasible to test each individual option in the true and false states, testing every state in conjunction with every other state requires an exponential amount of time. For programs with loops, testing every number of loop iterations is likely to be highly time consuming.

There is plenty of code you can't see

Even if you cover every line of source code, the compiler may still thwart your valiant efforts. Optimising compilers like to inline code (make copies of it) and specialise code (freeze in some details that would otherwise be dynamic). After such transformations, the compiler might spot undefined behaviour (something almost all C/C++ programs contain) and make modifications that break your code. You might have tested all the source code, but you have not tested all the code generated by the compiler. If you are writing in C/C++, and undefined behaviour and optimisation doesn't scare you a lot, you should read this LLVM article series.

Functions have huge inputs

Testing functions typically involves supplying their input and inspecting their output. Usually the input space is too large to enumerate - which is likely to be the case even if your function takes in an integer. As soon as your function takes a string or array, enumeration is definitely infeasible. Often you can pick cases at which the code is likely to go wrong (0, 1, -1, maxBound) - but maybe it only fails for Carmichael numbers. Random testing can help, and is always advisable, but the effort to deploy random testing is typically quite a bit higher than input/output samples, and it is no panacea.

Functions are not functions

Testing functions usually assumes they really are functions, which depend only on their input. In pure functional languages that is mostly true, but in C/C++ it is less common. For example, functions that have an internal cache might behave differently under parallelism, especially if their cache is not managed properly. Functions may rely on global variables, so they might perform correctly until some seemingly unrelated operation is performed. Even Haskell programs are likely to depend on global state such as the FPU flags, which may be changed unexpectedly by other code.

In my experience, the non-functional nature of functions is one of the biggest practical difficulties, and is also a common place where dependency changes cause frustration. Buggy code can work successfully for years until an improved memory allocator allows a race condition to be hit.

Performance testing is hard

Even if your code gives the correct results, it may take too long or use too much memory. Alas, testing for resource usage is difficult. Resource numbers, especially runtime, are often highly variable between runs - more so if tests are run on shared hardware or make use of parallelism. Every dependency change is likely to have some impact on resource usage, perhaps as dependencies themselves chose to trade time for memory. Spotting erroneous variations often requires a human to make a judgement call.

What is the solution?

Tests help, and are valuable, and you should aim to test as much as you can. But for any reasonably sized program, your tests will never be complete, and the program will always contain unknown bugs. Most likely someone using your code will stumble across one of these bugs. In this case, it's often possible (and indeed, highly desirable) to add a new test case specifically designed to spot this error. Bugs have a habit of recurring, and a bug that happens twice is just embarrassing.

Thinking back to dependency versions, there is often strength in numbers. If all your users are on the same version of all the dependencies, then any bug that is very common is likely to be found by at least one user and fixed for all.

Thinking more generally, it is clear that many of these issues are somewhat ameliorated by pure functional programming. I consider testability and robustness to be one of the great strengths of Haskell.

Categories: Offsite Blogs

Redundant entries in .cabal file?

haskell-cafe - Sat, 08/15/2015 - 3:00pm
Hi all, Does anyone know why I’m getting redundant entries in my ‘cabal init’ generated .cabal file: library exposed-modules: Language.Broker, Language.Broker ? Is it because I’m using a *.hsc file, as my source, and cabal is finding both files: Broker.hsc, and Broker.hs in the Language directory? Thanks, -db _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe< at >
Categories: Offsite Discussion

Cross-compiling fails for package 'directory'

haskell-cafe - Sat, 08/15/2015 - 1:46pm
Following <>, I have built a cross-compiling ghc for creating programs that run on the raspberry pi. This ghc has built a "hello world" program that runs on the rpi: OK so far. Unfortunately, building the package 'directory-' with this cross- compiler fails with the following error message: "System/Directory/Internal.hsc:31 directive const_str cannot be handled in cross-compilation mode" The offending function from System.Directory is this one: Although one can imagine that the meaning of this function is tricky when cross-compiling, I don't think that has actually anything to do with the error. The problem is that hsc2hs cannot handle this 'const_str' directive; see <>. Now my question: how can this be fixed? Is the failure of hsc2hs to support this directive just a matter of "not implemented right now", maybe by lack of
Categories: Offsite Discussion

Reactive config file generation

haskell-cafe - Sat, 08/15/2015 - 10:48am
Hi all, I am using Apache Zookeeper as a service directory: I have a bunch of services which announce their presence by making nodes in Zookeeper, so that dependent services can update their configuration to make use of the available services, and stop trying to use services that have died. Zookeeper is a pretty nice fit for this because it supports watching a node for changes, so in theory there is no need to poll Zookeeper periodically. The services that I control work with this just fine, but there are some (e.g. an Nginx reverse-proxy) that are reconfigured using the rather more common approach of updating a file (or files) and then sending the process a signal. I am currently pondering how to make this work without polling, or manually triggering a refresh script, which is how it is currently done. I've never used FRP, but am at least vaguely aware of it and from my high-level understanding it seems like this could be a very good fit. The Zookeeper state is a time-varying value which I want to conver
Categories: Offsite Discussion

TExpQ a to a?

Haskell on Reddit - Sat, 08/15/2015 - 10:12am
-- Function: maybeParseTextTH :: TExpQ (Text -> Maybe a) -> Text -> TExpQ a maybeParseTextTH mk txt = case (??? what should I put here ??? mk) txt of Just _ -> [|| fromJust $ $$mk $$(textTExp txt) ||] Nothing -> fail ("Parse error " ++ show txt) -- I want to use it like this: parseSomethingTH :: Text -> TExpQ Something parseSomethingTH = maybeParseTextTH [|| parseSomething ||] submitted by lamefun
[link] [comment]
Categories: Incoming News

stack/cabal repl zsh prompt indicator

Haskell on Reddit - Sat, 08/15/2015 - 6:25am

I created a small indicator for stack projects/cabal projects as I am working with multiple versions of ghc (btw. thanks hvr for the ppa-repo) and often do not have the correct ghc version in my path, maybe it is useful to some of you. It is based on one of the many "cabal sandbox indicators for zsh" i found using google.

cabal sandboxes are indicated by a ghc version liked [7.10.2]

  • green ghc version indicates that there is a cabal project, and there exists a directory in the sandbox with libraries built with the current ghc (in the path)

  • a list of red ghc versions indicates cabal projects, which would be available

for stack projects the indicator is like: [rts-3.0|7.10.0]

  • green resolver info and green ghc version indicate a proper stack project

  • red resolver info indicate that the current resolver is not initialized

submitted by epsilonhalbe
[link] [2 comments]
Categories: Incoming News

Documenting generated declarations?

Haskell on Reddit - Sat, 08/15/2015 - 5:22am

There seem to be no Template Haskell structures for code comments or documentation. Is there a way to document declarations generated by it?

submitted by lamefun
[link] [5 comments]
Categories: Incoming News

C-style fork with ContT

Haskell on Reddit - Sat, 08/15/2015 - 5:18am

The thread about monads as variable substitution happened to make me think of the continuation monad's ability to bind the same variable several times, and I realized how easy it would be to implement C-style fork. Maybe this exists in a library somewhere, I just decided to try it and see if it might be of use as a refresher on continuations.

Let's see if my literate Haskell will collaborate with Reddit's formatting...

The continuation monad is a little scary, but it's also useful when you want to do something unusual with your control flow.

Like what?

Consider the fork function in Unix. It works differently from Haskell's forkIO in that instead of accepting a function to run in the background, it returns twice, once for the parent, and once for the child.

That can be a mind-bender since we're used to thinking of programs as progressing linearly, but the name fork tips us off that they can branch, too.

So the fork function introduces a split in the program's execution, and by checking its return value, the remainder of the program can figure out whether it's executing as the parent or as the child.

It's like if your mind was cloned and you woke up in two different places, you would just check where you are and then go on with your day.

So how can we implement this funny operation in Haskell? ContT and IO to the rescue! The continuation monad grants us access, whenever we want, to a representation of the remainder of the program, and lets us execute it twice with no questions asked.

> module Fork where > > import Control.Monad (void) > import Control.Monad.IO.Class (liftIO) > import Control.Monad.Cont (ContT, runContT, callCC) > import Control.Concurrent (forkIO)

In C, fork returns a boolean, but it's clearer to use a sum type.

> data Forking = Parent | Child

So let's look at an example program. I'll make the parent print a backslash and the child print a slash, and then they'll both print a period and newline. The liftIO is necessary to embed IO actions inside the ContT transformer.

> main :: IO () > main = runForking $ do > status <- fork > case status of > Parent -> liftIO (putStr "\\") > Child -> liftIO (putStr "/") > liftIO (putStrLn ".")

Here's how we turn these ContT computations into IO computations using runContT.

Note that ContT has three type variables, like this:

newtype ContT r m a :: * -> (* -> *) -> * -> *

Here r means "final result," m means "underlying monad" and a means "intermediate value."

The final result is what's returned by the final continuation, which we must provide when we run the ContT computation. The final continuation receives the intermediate value and returns an action of the underlying monad that produces the final result.

We don't really care about the final result, so let's just set it to () and not think about it too much.

> runForking :: ContT () IO a -> IO () > runForking m = runContT m (const (return ()))

Let's define a little function just to make the actual IO forking look cleaner:

> inBackground :: IO () -> ContT () IO () > inBackground = void . liftIO . forkIO

And now the main course! Here we use callCC which gives us access to a function representing the remainder of the execution. The type of that function goes from Forking to ContT () IO Forking.

Since Forking only has two different values, we can see this function as a kind of pair of continuations. I'll construct this pair just for demonstrative purposes.

> fork :: ContT () IO Forking > fork = callCC $ \k -> do > let (childK, parentK) = (k Child, k Parent) > inBackground (runForking childK) > parentK

Now we can run it:

Fork> main \. /.

Voila, both branches are run.

submitted by mioloko
[link] [8 comments]
Categories: Incoming News

Summer Haskell Course

Haskell on Reddit - Sat, 08/15/2015 - 4:40am
Categories: Incoming News

What did "=>>" and ">>=" mean?

Haskell on Reddit - Fri, 08/14/2015 - 11:04pm

Hi I am a new comer. I want to know what did "=>>" and ">>=" (in monad and comonad) mean in Haskell. I found these symbols in this piece of codes:

submitted by rule_110
[link] [14 comments]
Categories: Incoming News

A type level puzzle

haskell-cafe - Fri, 08/14/2015 - 10:46pm
For the type level gurus: I would like to define types Sum :: [Field] -> * (:::) :: String -> * -> Field used like this Sum '[ "foo" ::: a, "bar" ::: b, "baz" ::: c ] (I hope this makes sense. I'm not quite familiar with the syntax.) such that Sum '[ s1 ::: a1, ... ] unifies with Sum '[ s1 ::: b1, ... ] to give Sum '[ s1 ::: c1, ... ] where c1 is the unification of a1 and b1. If sn is absent from exactly one of the unificands then its type is copied over unchanged. If sn is absent from both then it is absent from the unification. The types should also be invariant under permutation of the list. This is perhaps a bit obscure so I'll explain the application. This is intended for the sumtype equivalent of a record type, so if we have Sum '[ "foo" ::: a, "bar" ::: b ] and Sum '[ "foo" ::: a, "baz" ::: c ] then I take take the sum of these sums and get something of type Sum '[ "foo" ::: a, "bar" ::: b, "baz" ::: c ] If it makes it easier than I am happy
Categories: Offsite Discussion

Can someone explain the "Monads are generalised variable substitution" interpretation?

Haskell on Reddit - Fri, 08/14/2015 - 10:18pm

So, I occasionally see this interpretation come up when dealing with ASTs, and sometimes see ASTs implement the monad class with return = Var.

What's the background for it? Are there any resources out there explaining it?

submitted by deltaSquee
[link] [14 comments]
Categories: Incoming News

How to model outer space for a MUD

haskell-cafe - Fri, 08/14/2015 - 9:34pm
Star Wars MUD has a 3-D coordinate system such that (0,0,0) is some planet. I'm curious as to how one might model this system that could simulate a ship's movement through a 3-D grid. Matrix, 3-D array, graph. None of these? Ideas? _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe< at >
Categories: Offsite Discussion

"Could not list sources" warning in sandboxed project with add-source deps

haskell-cafe - Fri, 08/14/2015 - 8:00pm
I'm getting a warning when building a sandboxed project with add-source dependencies.  I tried increasing the verbosity of cabal, but it still won't tell me what's going wrong so I can fix it. Any suggestions on how to debug or fix this? thanks,--Eric _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe< at >
Categories: Offsite Discussion

Help installing a package using stack.

Haskell on Reddit - Fri, 08/14/2015 - 1:59pm

Hi guys!

I'm very new to the stack framework, trying out my first project using it. Not sure this is the right place to look for help in this matter.

I'm trying to install the following package:

Using: stack install hsexif

In the directory I previously ran stack init.

Now I would like to use ghci in the directory/project. So I run stack ghci and try to import hsexif:

*Lib> import Graphics.HsExif

<no location info>: Could not find module ‘Graphics.HsExif’ It is a member of the hidden package ‘hsexif-’.

Is the package installed wrong/not installed? I'm doing something wrong?

Kind regards, João


EDIT: Adding hsexif to the build-depends on the cabal solved the problem! :) Thank you very much for all your help!

submitted by Winke
[link] [16 comments]
Categories: Incoming News