Search code examples
haskellparse-error

Haskell: Parse error in pattern: acc


I found some Cloud Haskell Demos and I try to run it, but I get an error and I don't know why. The error looks like:

MasterSlave.hs:18:9: Parse error in pattern:acc

The code from MasterSlave.hs is:

module MasterSlave where

import Control.Monad
import Control.Distributed.Process
import Control.Distributed.Process.Closure
import PrimeFactors

slave :: (ProcessId, Integer) -> Process ()
slave (pid, n) = send pid (numPrimeFactors n)

remotable ['slave]

-- | Wait for n integers and sum them all up
sumIntegers :: Int -> Process Integer
sumIntegers = go 0
  where
    go :: Integer -> Int -> Process Integer
    go !acc 0 = return acc
    go !acc n = do
      m <- expect
      go (acc + m) (n - 1)

data SpawnStrategy = SpawnSyncWithReconnect
                   | SpawnSyncNoReconnect
                   | SpawnAsync
  deriving (Show, Read)

master :: Integer -> SpawnStrategy -> [NodeId] -> Process Integer
master n spawnStrategy slaves = do
  us <- getSelfPid

  -- Distribute 1 .. n amongst the slave processes
  spawnLocal $ case spawnStrategy of
    SpawnSyncWithReconnect ->
      forM_ (zip [1 .. n] (cycle slaves)) $ \(m, there) -> do
        them <- spawn there ($(mkClosure 'slave) (us, m))
        reconnect them
    SpawnSyncNoReconnect ->
      forM_ (zip [1 .. n] (cycle slaves)) $ \(m, there) -> do
        _them <- spawn there ($(mkClosure 'slave) (us, m))
        return ()
    SpawnAsync ->
      forM_ (zip [1 .. n] (cycle slaves)) $ \(m, there) -> do
        spawnAsync there ($(mkClosure 'slave) (us, m))
        _ <- expectTimeout 0 :: Process (Maybe DidSpawn)
        return ()

  -- Wait for the result
  sumIntegers (fromIntegral n)

What is wrong with this code?


Solution

  • You need to have two language extensions enabled, BangPatterns and TemplateHaskell. These can be enabled in two ways:

    1. From the command line when compiling
    2. In the source file the extension is being used (preferred)

    To enable them at the command line, pass the flag -XExtensionName for each extension you need, so for your case you'd have ghc -XTemplateHaskell -XBangPatterns source_file_name.hs.

    To enable them in source, use the {-# LANGUAGE ExtensionName #-} pragma at the top of the file:

    {-# LANGUAGE TemplateHaskell #-}
    {-# LANGUAGE BangPatterns #-}
    module MasterSlave where
    
    ...
    

    Language extensions are a pretty big part of GHC Haskell. There are some that are so common that they appear in most every real world application, like OverloadedStrings which allows you to use Text and Bytestring with String literal syntax, and MultiParamTypeClasses is indispensable for many of the more advanced libraries like lens and mtl. Other common ones include the Derive* extensions like DeriveFunctor, DeriveFoldable, etc, that let the compiler derive more extensions than just the standard Eq, Show, Read, and co.

    In your case, BangPatterns adds syntax for specifying extra strictness in function arguments and data type fields. This helps reduce problems from implicit laziness, but it can also be used with too heavy a hand if you aren't careful. TemplateHaskell enabled a lot of extra syntax for a templating/macro language built in to GHC. Library authors can write template Haskell functions that take in a data type, expression, function name, or other constructs and build boilerplate code that doesn't need to be left to the user, but isn't easy or succinct to abstract otherwise. The lens library uses it a lot, along with the Yesod web framework.