After I have read the example of a RPN calculator in "Learn You a Haskell for Great Good!" I wanted to rewrite it myself in a more general way.
In order to easily extend the available functions I put these in separated lists and pattern matched with the lookup
function using the ViewPatterns
syntax. To read the input with read
I wrote this:
parse xs x = case readMaybe x of
Just x -> Right (x : xs)
Nothing -> Left "Syntax error
but I'd rather avoid a case expression and use again the view pattern like this:
parse xs (readMaybe -> Just x ) = Right (x : xs)
parse xs (readMaybe -> Nothing) = Left "Syntax error"
However with the latter I'm getting this error:
No instance for (Read a0) arising from a use of ‘readMaybe’
I don't understand why. Aren't they equivalent?
The whole code is here.
The syntax of the SQL CASE expression is: CASE [expression] WHEN condition_1 THEN result_1 WHEN condition_2 THEN result_2 ... WHEN condition_n THEN result_n ELSE result END case_name The CASE statement can be written in a few ways, so let’s take a look at these parameters. The parameters or components of the CASE SQL statement are:
The expressions are used within each condition without mentioning it at the start of the CASE statement. For example: CASE WHEN name = 'John' THEN 'Name is John' WHEN name = 'Steve' THEN 'Name is Steve' END
The CASE expression returns a result whose data type depends on the context where it is used. For example, if the CASE expression is used in the character string context, it returns the result as a character string. If the CASE expression is used in a numeric context, it returns the result as an integer, a decimal, or a real value.
There are actually two ways to use an SQL CASE statement, which are referred to as a “simple case expression” or a “searched case expression”. The expression is stated at the beginning, and the possible results are checked in the condition parameters.
They're not equivalent. The case
version has one readMaybe
, the view pattern version has two. For every readMaybe
, the compiler has to infer which type is the target of the attempt to read. When the code says
parse xs x = case readMaybe x of
Just x -> Right (x : xs)
Nothing -> Left "Syntax error
the GHC detective notices that in your Just x
case, x
ends up consed to xs
, and so must take whatever type the elements of xs
have. And that's good work.
But when you write
parse xs (readMaybe -> Just x ) = Right (x : xs)
parse xs (readMaybe -> Nothing) = Left "Syntax error"
you create two separate find-the-target-type problems, one for each use of readMaybe
. The first of these is solved in just the same way as in the case
case, but for the second, read individually,
parse xs (readMaybe -> Nothing) = Left "Syntax error"
there is just no clue what it is that you are failing to read, and no reason to believe it is the same thing as in the line above.
Generally, it is inappropriate to use view patterns unless there is only one outcome of interest. They are the wrong syntax if you want to do an intermediate computation once, but analyse the result into more than one case. I am happy to remain on the record that I consider them a misfeature for this reason.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With