Execute HQ9+/Haskell: Difference between revisions

From Rosetta Code
Content added Content deleted
(does not work fine for '+')
(Added the case to deal with the increment instruction, and removed the notice)
Line 1: Line 1:
{{implementation|HQ9+}}{{collection|RCHQ9+}}
{{implementation|HQ9+}}{{collection|RCHQ9+}}
This [[HQ9+]] interpreter is written in [[Haskell]].
This [[HQ9+]] interpreter is written in [[Haskell]].
We use [https://hackage.haskell.org/package/base-4.11.1.0/docs/Data-Traversable.html#v:mapAccumR mapAccumR] to maintain the accumulator.
{{incomplete|haskell|Command '+' is treated incorrectly. Implementing the accumulator in Haskell is not trivial because it has no variables.}}
However, the specification doesn't say what to do with said accumulator on completion.
<lang haskell>import Char (toLower, toUpper)
<lang haskell>module Main where


import Data.Char (toLower, toUpper)
main = interact hq9p
import Data.List -- for concat
import Data.Traversable -- for mapAccumR


hq9p :: String -> String
main :: IO ()
main = do
hq9p source = concatMap run $ map toLower source
s <- getLine
where run 'h' = "Hello, world!\n"
putStrLn (snd (hq9p s))
run 'q' = source

run '9' = bottles
hq9p :: String -> (Int,String)
run _ = ""
hq9p src = fin $ mapAccumR run 0 $ map toLower src
-- Obviously, the final case works just fine for '+'.
where
fin (acc,log) = (acc,concat log)
run acc ch = case ch of
'h' -> (acc,"Hello, world!")
'q' -> (acc,src)
'9' -> (acc,bottles)
'+' -> (acc + 1,"")
'_' -> (acc,"")


bottles :: String
bottles :: String
bottles = concat
bottles = [99, 98 .. 0] >>= beers
where
[up (bob n) ++ wall ++ ", " ++ bob n ++ ".\n" ++
beers n = unlines [
pass n ++ bob (n - 1) ++ wall ++ ".\n\n" |
n <- [99, 98 .. 0]]
bob n ++ " on the wall, " ++ bob n ++ ".",
where bob n = num n ++ " bottle" ++ s n ++ " of beer"
pass n ++ bob (n - 1) ++ " on the wall.\n"]
wall = " on the wall"
bob n =
pass 0 = "Go to the store and buy some more, "
let nu = case n of { (-1) -> "99"; 0 -> "No more"; n -> show n; }
pass _ = "Take one down and pass it around, "
s = if n == 1 then "" else "s"
up (x : xs) = toUpper x : xs
in nu ++ " bottle" ++ s ++ " of beer"
num (-1) = "99"
pass n = case n of
num 0 = "no more"
0 -> "Go to the store and buy some more, "
num n = show n
_ -> "Take one down and pass it around, "</lang>
s 1 = ""
s _ = "s"</lang>

Revision as of 14:36, 13 July 2018

Execute HQ9+/Haskell is an implementation of HQ9+. Other implementations of HQ9+.
Execute HQ9+/Haskell is part of RCHQ9+. You may find other members of RCHQ9+ at Category:RCHQ9+.

This HQ9+ interpreter is written in Haskell. We use mapAccumR to maintain the accumulator. However, the specification doesn't say what to do with said accumulator on completion. <lang haskell>module Main where

import Data.Char (toLower, toUpper) import Data.List -- for concat import Data.Traversable -- for mapAccumR

main :: IO () main = do

 s <- getLine
 putStrLn (snd (hq9p s))

hq9p :: String -> (Int,String) hq9p src = fin $ mapAccumR run 0 $ map toLower src

 where
   fin (acc,log) = (acc,concat log)
   run acc ch = case ch of
     'h' -> (acc,"Hello, world!")
     'q' -> (acc,src)
     '9' -> (acc,bottles)
     '+' -> (acc + 1,"")
     '_' -> (acc,"")

bottles :: String bottles = [99, 98 .. 0] >>= beers

 where
   beers n = unlines [
     bob n ++ " on the wall, " ++ bob n ++ ".",
     pass n ++ bob (n - 1) ++ " on the wall.\n"]
   bob n =
     let nu = case n of { (-1) -> "99"; 0 -> "No more"; n -> show n; }
         s  = if n == 1 then "" else "s"
     in nu ++ " bottle" ++ s ++ " of beer"
   pass n = case n of
     0 -> "Go to the store and buy some more, "
     _ -> "Take one down and pass it around, "</lang>