Content advisory: This is a half-baked research post.
Abstract. Top-level unpacking of existentials are easy to integrate into Hindley-Milner type inference. Haskell should support them. It’s possible this idea can work for internal bindings of existentials as well (ala F-ing modules) but I have not worked out how to do it.
Update. And UHC did it first!
Update 2. And rank-2 type inference is decidable (and rank-1 existentials are an even weaker system), although the algorithm for rank-2 inference requires semiunification.
Read more...
ghc --make is a useful mode in GHC which automatically determines what modules need to be compiled and compiles them for you. Not only is it a convenient way of building Haskell projects, its single-threaded performance is good too, by reusing the work of reading and deserializing external interface files. However, the are a number of downsides to ghc --make:
- Projects with large module graphs have a hefty latency before recompilation begins. This is because
ghc --make (re)computes the full module graph, parsing each source file’s header, before actually doing any work. If you have a preprocessor, it’s even worse. - It’s a monolithic build system, which makes it hard to integrate with other build systems if you need something more fancy than what GHC knows how to do. (For example, GHC’s painstakingly crafted build system knows how to build in parallel across package boundaries, which Cabal has no idea how to do.)
- It doesn’t give you any insight into the performance of your build, e.g. what modules take a long time to build or what the big “blocker” modules are.
ghc-shake is a reimplementation of ghc --make using the Shake build system. It is a drop-in replacement for ghc. ghc-shake sports the following features:
Read more...
Abstract. The traditional abstraction barriers between compiler, build system and package manager are increasingly ill-suited for IDEs, parallel build systems, and modern source code organization. Recent compilers like go and rustc are equipped with a fully-fledged build systems; semantic build systems like Bazel and Gradle also expect to manage the packaging of software. Does this mean we should jettison these abstraction barriers? It seems worthwhile to look for new interfaces which can accommodate these use-cases.
Read more...
The essence of stateless user interface is that actions you take with a program should not depend on implicit state. Stateless interfaces are easier to understand, because an invocation of a command with some arguments will always do the same thing, whereas in a stateful interface, the command may do some different than it did yesterday, because that implicit state has changed and is influencing the meaning of your program.
Read more...
You might be wondering: with the beta release of no-reinstall Cabal, is this functionality be coming to GHC 8.0? (Or even a new release of Cabal, since the no-reinstall feature works with GHC 7.10). Unfortunately, there is a split among the Cabal developers over whether or not the actual no-reinstall behavior should go into Cabal by default as is. Duncan Coutts, in particular, has argued that it’s a bad idea to enable no-reinstall without other (unimplemented) changes to Cabal. Since the extra needed changes are not fully implemented yet, it’s unclear if Duncan will manage them for GHC 8.0.
Read more...
Over this summer, Vishal Agrawal has been working on a GSoC project to move Cabal to more Nix-like package management system. More simply, he is working to make it so that you’ll never get one of these errors from cabal-install again:
Resolving dependencies...
In order, the following would be installed:
directory-1.2.1.0 (reinstall) changes: time-1.4.2 -> 1.5
process-1.2.1.0 (reinstall)
extra-1.0 (new package)
cabal: The following packages are likely to be broken by the reinstalls:
process-1.2.0.0
hoogle-4.2.35
haskell98-2.0.0.3
ghc-7.8.3
Cabal-1.22.0.0
...
However, these patches change a nontrivial number of moving parts in Cabal and cabal-install, so it would be very helpful to have willing guinea pigs to help us iron out some bugs before we merge it into Cabal HEAD. As your prize, you’ll get to run “no-reinstall Cabal”: Cabal should never tell you it can’t install a package because some reinstalls would be necessary.
Read more...
Another half year, another Ubuntu upgrade. This upgrade went essentially smoothly: the only things that stopped working were my xbindkeys bindings for volume and suspend, which were easy to fix.
Volume up and down
If you previously had:
#Volume Up
"pactl set-sink-volume 0 -- +5%"
m:0x10 + c:123
Mod2 + XF86AudioRaiseVolume
this syntax no longer works: you must place the double dash earlier in the command, as so:
#Volume Up
"pactl -- set-sink-volume 0 +5%"
m:0x10 + c:123
Mod2 + XF86AudioRaiseVolume
Do the same for volume down.
Read more...
My usual laptop setup is I have a wide monitor, and then I use my laptop screen as a secondary monitor. For a long time, I had two XMonad layouts: one full screen layout for my laptop monitor (I use big fonts to go easy on the eyes) and a two-column layout when I’m on the big screen.
But I had an irritating problem: if I switched a workspace from the small screen to the big screen, XMonad would still be using the full screen layout, and I would have to Alt-Tab my way into the two column layout. To add insult to injury, if I moved it back, I’d have to Alt-Tab once again.
Read more...
tl;dr A non-nameless term equipped with a map specifying a de Bruijn numbering can support an efficient equality without needing a helper function. More abstractly, quotients are not just for proofs: they can help efficiency of programs too.
The cut. You’re writing a small compiler, which defines expressions as follows:
type Var = Int
data Expr = Var Var
| App Expr Expr
| Lam Var Expr
Where Var is provided from some globally unique supply. But while working on a common sub-expression eliminator, you find yourself needing to define equality over expressions.
Read more...
A while ago, I wrote a post describing how unsafe FFI calls could block your entire system, and gave the following example of this behavior:
/* cbit.c */
#include <stdio.h>
int bottom(int a) {
while (1) {printf("%d\n", a);sleep(1);}
return a;
}
/* cbit.h */
int bottom(int a);
/* UnsafeFFITest.hs */
{-# LANGUAGE ForeignFunctionInterface #-}
import Foreign.C
import Control.Concurrent
main = do
forkIO $ do
safeBottom 1
return ()
yield
print "Pass (expected)"
forkIO $ do
unsafeBottom 2
return ()
yield
print "Pass (not expected)"
foreign import ccall "cbit.h bottom" safeBottom :: CInt -> IO CInt
foreign import ccall unsafe "cbit.h bottom" unsafeBottom :: CInt -> IO CInt
In the post, I explained that the reason this occurs is that unsafe FFI calls are not preemptible, so when unsafeBottom loops forever, the Haskell thread can’t proceed.
Read more...