molleweide

molleweide

Effective Haskell: Calculator throws errors in parse'

@RebeccaSkinner,

Allright, so I have put all of the example code for Calculator in chapter 4 on page ~140 in a file and when loading it into GHCI it throws this:

    λ: :reload
    [1 of 1] Compiling Calculator       ( Calculator.hs, interpreted )

    Calculator.hs:40:9: error:
        • Couldn't match expected type ‘String -> Either String a1’
                      with actual type ‘Either String b0’
        • In the pattern: Left err
          In a case alternative: Left err -> Left err
          In the expression:
            case readEither of
              Left err -> Left err
              Right lit' -> Right (Lit lit', rest)
       |
    40 |         Left err -> Left err
       |         ^^^^^^^^

    Calculator.hs:41:9: error:
        • Couldn't match expected type ‘String -> Either String a1’
                      with actual type ‘Either a0 Int’
        • In the pattern: Right lit'
          In a case alternative: Right lit' -> Right (Lit lit', rest)
          In the expression:
            case readEither of
              Left err -> Left err
              Right lit' -> Right (Lit lit', rest)
       |
    41 |         Right lit' -> Right (Lit lit', rest)
       |         ^^^^^^^^^^
    Failed, no modules loaded.

I am not sure if maybe there is something that you forgot to add or that should be added.

Below I post my full calculator module:

module Calculator where

import Text.Read (readEither)

data Expr = Lit Int
  | Add Expr Expr
  | Sub Expr Expr
  | Mul Expr Expr
  | Div Expr Expr

eval :: Expr -> Int
eval expr =
  case expr of
    Lit num -> num
    Add arg1 arg2 -> eval' ( + ) arg1 arg2
    Sub arg1 arg2 -> eval' ( - ) arg1 arg2
    Mul arg1 arg2 -> eval' ( * ) arg1 arg2
    Div arg1 arg2 -> eval' div arg1 arg2
    where
      eval' :: (Int -> Int -> Int) -> Expr -> Expr -> Int
      eval' operator arg1 arg2 = operator (eval arg1) (eval arg2)

parse :: String -> Either String Expr
parse str =
  case parse' (words str) of
    Left err          -> Left err
    Right (e, [])     -> Right e
    Right (_, rest)   -> Left $ "Found extra tokens: " <> (unwords rest)

parse' :: [String] -> Either String (Expr, [String])
parse' [] = Left "unexpected end of expression"
parse' (token:rest) =
  case token of
    "+" -> parseBinary Add rest
    "*" -> parseBinary Mul rest
    "-" -> parseBinary Sub rest
    "/" -> parseBinary Div rest
    lit ->
      case readEither of
        Left err -> Left err
        Right lit' -> Right (Lit lit', rest)

parseBinary :: (Expr -> Expr -> Expr) -> [String] -> Either String (Expr, [String])
parseBinary exprConstructor args =
  case parse' args of
    Left err -> Left err
    Right (firstArg, rest') ->
      case parse' rest' of
        Left err -> Left err
        Right (secondArg, rest'') ->
          Right $ (exprConstructor firstArg secondArg, rest'')

run :: String -> String
run expr =
  case parse expr of
    Left err -> "Error: " <> err
    Right expr' ->
      let answer = show $ eval expr'
      in "The answer is: " <> answer

First Post!

RebeccaSkinner

RebeccaSkinner

Author of Effective Haskell

Hi, it looks like you’re missing the lit parameter to readEither in the parse' function. The correct version of the function is:

parse' :: [String] -> Either String (Expr, [String])
parse' [] = Left "unexpected end of expression"
parse' (token:rest) =
  case token of
    "+" -> parseBinary Add rest
    "*" -> parseBinary Mul rest
    "-" -> parseBinary Sub rest
    "/" -> parseBinary Div rest
    lit ->
      case readEither lit of
        Left err -> Left err
        Right lit' -> Right (Lit lit', rest)

It looks like this is fixed in the most recent version- thanks for the catch and sorry for the trouble!

Where Next?

Popular Pragmatic Bookshelf topics Top

jimschubert
In Chapter 3, the source for index introduces Config on page 31, followed by more code including tests; Config isn’t introduced until pag...
New
mikecargal
Title: Hands-On Rust (Chapter 11: prefab) Just played a couple of amulet-less games. With a bit of debugging, I believe that your can_p...
New
Mmm
Hi, build fails on: bracket-lib = “~0.8.1” when running on Mac Mini M1 Rust version 1.5.0: Compiling winit v0.22.2 error[E0308]: mi...
New
jeremyhuiskamp
Title: Web Development with Clojure, Third Edition, vB17.0 (p9) The create table guestbook syntax suggested doesn’t seem to be accepted ...
New
jgchristopher
“The ProductLive.Index template calls a helper function, live_component/3, that in turn calls on the modal component. ” Excerpt From: Br...
New
s2k
Hi all, currently I wonder how the Tailwind colours work (or don’t work). For example, in app/views/layouts/application.html.erb I have...
New
kolossal
Hi, I need some help, I’m new to rust and was learning through your book. but I got stuck at the last stage of distribution. Whenever I t...
New
jwandekoken
Book: Programming Phoenix LiveView, page 142 (157/378), file lib/pento_web/live/product_live/form_component.ex, in the function below: d...
New
New
dachristenson
@mfazio23 Android Studio will not accept anything I do when trying to use the Transformations class, as described on pp. 140-141. Googl...
New

Other popular topics Top

Devtalk
Reading something? Working on something? Planning something? Changing jobs even!? If you’re up for sharing, please let us know what you’...
1063 24245 395
New
PragmaticBookshelf
Instantly view the changes you make to an app with stateful hot reload, and define a declarative UI in the same language as the app logic...
New
New
PragmaticBookshelf
Learn different ways of writing concurrent code in Elixir and increase your application's performance, without sacrificing scalability or...
New
husaindevelop
Inside our android webview app, we are trying to paste the copied content from another app eg (notes) using navigator.clipboard.readtext ...
New
First poster: bot
zig/http.zig at 7cf2cbb33ef34c1d211135f56d30fe23b6cacd42 · ziglang/zig. General-purpose programming language and toolchain for maintaini...
New
PragmaticBookshelf
25 puzzles that will make you a better C programmer by challenging your knowledge of the language, and explaining the technical details o...
New
PragmaticBookshelf
Get the comprehensive, insider information you need for Rails 8 with the new edition of this award-winning classic. Sam Ruby @rubys ...
New
AstonJ
This is cool! DEEPSEEK-V3 ON M4 MAC: BLAZING FAST INFERENCE ON APPLE SILICON We just witnessed something incredible: the largest open-s...
New
xiji2646-netizen
There’s a GitHub repo at forrestchang/andrej-karpathy-skills that’s sitting at 97.8k stars. It’s a single CLAUDE.md file with four behavi...
New

Sub Categories: