Execute HQ9+/Haskell: Difference between revisions

From Rosetta Code
Content added Content deleted
(does not work fine for '+')
m (Fixed syntax highlighting.)
 
(One intermediate revision by one other user not shown)
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)
<syntaxhighlight 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, "</syntaxhighlight>
s 1 = ""
s _ = "s"</lang>

Latest revision as of 10:15, 1 September 2022

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.

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, "