Why you should abandon C++ and embrace Haskell

Ryan Yates

http://goo.gl/74IKDX

Hieroglyphs are fun!

BASIC is fun too!

http://augustss.blogspot.com/2009/02/more-basic-not-that-anybody-should-care.html

{-# LANGUAGE ExtendedDefaultRules, OverloadedStrings #-}
import BASIC

main = runBASIC $ do
    10 GOSUB 1000
    20 PRINT "* Welcome to HiLo *"
    30 GOSUB 1000

    100 LET I := INT(100 * RND(0))
    200 PRINT "Guess my number:"
    210 INPUT X
    220 LET S := SGN(I-X)
    230 IF S <> 0 THEN 300

    240 FOR X := 1 TO 5
    250   PRINT X*X;" You won!"
    260 NEXT X
    270 STOP

    300 IF S <> 1 THEN 400
    310 PRINT "Your guess ";X;" is too low."
    320 GOTO 200

    400 PRINT "Your guess ";X;" is too high."
    410 GOTO 200

    1000 PRINT "*******************"
    1010 RETURN

    9999 END

Users

The problem with Haskell is that it's a language built on lazy evaluation and nobody's actually called for it.

XKCD

http://hackage.haskell.org/package/kansas-comet-0.3.1/

-- | 'send' sends a javascript fragement to a document.
-- The Text argument will be evaluated before sending (in case there is an error,
-- or some costly evaluation needs done first).
-- 'send' suspends the thread if the last javascript has not been *dispatched*
-- the the browser.
send :: Document -> T.Text -> IO ()
send doc js = atomically $ putTMVar (sending doc) $! js

-- | wait for a virtual-to-this-document's port numbers' reply.
getReply :: Document -> Int -> IO Value
getReply doc num = do
        atomically $ do
           db <- readTVar (replies doc)
           case Map.lookup num db of
              Nothing -> retry
              Just r -> do
                      writeTVar (replies doc) $ Map.delete num db
                      return r
http://hackage.haskell.org/package/Combinatorrent

eventLoop :: Process CF ST ()
eventLoop = do
    mTid <- liftIO myThreadId
    pc   <- asks parent
    ch   <- asks chan
    m <- liftIO . atomically $
        (readTChan ch >>= return . Left) `orElse`
        (readTChan pc >>= return . Right)
    case m of
        Left (IAmDying tid) -> handleIAmDying tid
        Left (SpawnNew chld) -> handleSpawnNew chld
        Right (PleaseDie tid) | tid == mTid -> handlePleaseDie
        _ -> return () -- Ignore these. Since the chan is duped, we get stray messages from above
http://hackage.haskell.org/package/git-annex

Assistant/Changes.hs:31:getChanges = (atomically . getTList) <<~ changePool
Assistant/Changes.hs:35:getAnyChanges = (atomically . takeTList) <<~ changePool
Assistant/Changes.hs:40:refillChanges cs = (atomically . flip appendTList cs) <<~ changePool
Assistant/Changes.hs:44:recordChange c = (atomically . flip snocTList c) <<~ changePool
Assistant/Commits.hs:19:getCommits = (atomically . getTList) <<~ commitChan
Assistant/Commits.hs:23:recordCommit = (atomically . flip consTList Commit) <<~ commitChan
Assistant/DaemonStatus.hs:32:getDaemonStatus = (atomically . readTMVar) <<~ daemonStatusHandle
Assistant/DaemonStatus.hs:41:           (s, b) <- atomically $ do
Assistant/DaemonStatus.hs:103:  liftIO $ atomically $ newTMVar $ addsync $ status
Assistant/DaemonStatus.hs:208:          =<< transferNotifier <$> atomically (readTMVar dstatus)
Assistant/DaemonStatus.hs:215:          =<< alertNotifier <$> atomically (readTMVar dstatus)
Assistant/NetMessager.hs:23:    (atomically . flip writeTChan m) <<~ (netMessages . netMessager)
Assistant/NetMessager.hs:26:waitNetMessage = (atomically . readTChan) <<~ (netMessages . netMessager)
Assistant/NetMessager.hs:45:    go nm = atomically $ do
Assistant/NetMessager.hs:61:    go v = atomically $ do
Assistant/NetMessager.hs:72:    go nm = atomically $ do
Assistant/NetMessager.hs:83:    liftIO $ atomically $ do
Assistant/NetMessager.hs:101:   liftIO $ atomically $ do
Assistant/NetMessager.hs:122:   stored <- liftIO $ atomically $ do
Assistant/NetMessager.hs:149:   liftIO $ atomically $ do
Assistant/NetMessager.hs:166:   liftIO $ atomically $

Assistant/Pushes.hs:24:         m <- atomically $ readTMVar v
Assistant/Pushes.hs:34: liftIO $ atomically $ store v . a . fromMaybe M.empty =<< tryTakeTMVar v
Assistant/RepoProblem.hs:20:    <$> (atomically . getTList) <<~ repoProblemChan
Assistant/RepoProblem.hs:34:    (atomically . flip consTList rp) <<~ repoProblemChan
Assistant/ScanRemotes.hs:24:    liftIO $ atomically $
Assistant/ScanRemotes.hs:33:    liftIO $ atomically $ do
Assistant/Threads/XMPPClient.hs:32:import Control.Concurrent.STM (atomically)
Assistant/Threads/XMPPClient.hs:99:             lasttraffic <- liftIO $ atomically . newTMVar =<< getC
Assistant/Threads/XMPPClient.hs:117:            void $ liftIO $ atomically . swapTMVar lasttraffic =<<
Assistant/Threads/XMPPClient.hs:126:            t <- liftIO $ atomically $ readTMVar lasttraffic
Assistant/TransferQueue.hs:44:getTransferQueue = (atomically . readTList . queuelist) <<~ transferQueu
Assistant/TransferQueue.hs:106:                 void $ liftIO $ atomically $
Assistant/TransferQueue.hs:115: l <- liftIO $ atomically $ readTList (deferreddownloads q)
Assistant/TransferQueue.hs:119:         liftIO $ atomically $ appendTList (deferreddownloads q) left
Assistant/TransferQueue.hs:147:         liftIO $ atomically $ ifM (checkRunningTransferSTM dstatus t)
Assistant/TransferQueue.hs:169: liftIO $ atomically $ do
Assistant/TransferQueue.hs:190: liftIO $ atomically $ do
Assistant/TransferQueue.hs:211: liftIO $ atomically $ do
Assistant/TransferQueue.hs:222: removed <- liftIO $ atomically $ dequeueTransfersSTM q c
Assistant/TransferrerPool.hs:28:        (mi, leftinpool) <- atomically (popTransferrerPool pool)
Assistant/TransferrerPool.hs:34:                then atomically $ pushTransferrerPool pool i

Assistant/TransferrerPool.hs:37:                        atomically $ pushTransferrerPool pool $ Transf
Assistant/Types/Buddies.hs:58:  <$> atomically (newTMVar noBuddies)
Assistant/Types/Buddies.hs:62:getBuddyList (v, _) = M.elems <$> atomically (readTMVar v)
Assistant/Types/Buddies.hs:65:getBuddy k (v, _) = M.lookup k <$> atomically (readTMVar v)
Assistant/Types/Buddies.hs:74:  changed <- atomically $ do
Assistant/Types/Changes.hs:27:newChangePool = atomically newTList
Assistant/Types/Commits.hs:19:newCommitChan = atomically newTList
Assistant/Types/NetMessager.hs:121:     (sp, rp) <- atomically $ (,) <$> gen <*> gen
Assistant/Types/NetMessager.hs:150:     <$> atomically newTChan
Assistant/Types/NetMessager.hs:151:     <*> atomically (newTMVar M.empty)
Assistant/Types/NetMessager.hs:152:     <*> atomically (newTMVar M.empty)
Assistant/Types/Pushes.hs:24:newFailedPushMap = atomically newEmptyTMVar
Assistant/Types/RepoProblem.hs:28:newRepoProblemChan = atomically newTList
Assistant/Types/ScanRemotes.hs:25:newScanRemoteMap = atomically newEmptyTMVar
Assistant/Types/TransferQueue.hs:26:newTransferQueue = atomically $ TransferQueue
Assistant/Types/TransferrerPool.hs:59:  mkcheck <- atomically $ fst <$> readTMVar p
Assistant/Types/TransferrerPool.hs:65:  dstatus <- atomically $ readTMVar dstatushandle
Command/NotifyChanges.hs:64:            maybe noop (atomically . writeTChan chan) sha
Command/NotifyChanges.hs:70:    r <- atomically $ readTChan chan
Command/NotifyChanges.hs:72:    rs <- atomically $ drain' chan
Command/WebApp.hs:151:  dstatus <- atomically . newTMVar =<< newDaemonStatus

Thanks!