如何用视图模式语法编写这个 case 表达式?

How to write this case expression with the view pattern syntax?

在阅读了 "Learn You a Haskell for Great Good!" 中 RPN calculator 的示例后,我想自己以更通用的方式重写它。

为了轻松扩展可用函数,我将它们放在单独的列表中,并使用 ViewPatterns 语法与 lookup 函数匹配。要使用 read 读取输入,我这样写:

parse xs x = case readMaybe x of
  Just x  -> Right (x : xs)
  Nothing -> Left "Syntax error

但我宁愿避免使用 case 表达式并再次使用这样的视图模式:

parse xs (readMaybe -> Just x ) = Right (x : xs)
parse xs (readMaybe -> Nothing) = Left "Syntax error"

但是对于后者我得到了这个错误: No instance for (Read a0) arising from a use of ‘readMaybe’

我不明白为什么。它们不是等价的吗?

整个代码为here.

它们不等同。 case版本有一个readMaybe,视图模式版本有两个。对于每个 readMaybe,编译器必须推断哪种类型是尝试读取的目标。当代码显示

parse xs x = case readMaybe x of
  Just x  -> Right (x : xs)
  Nothing -> Left "Syntax error

GHC 侦探注意到,在您的 Just x 案例中,x 最终同意 xs,因此必须采用 xs 的元素具有的任何类型。这很好。

但是当你写的时候

parse xs (readMaybe -> Just x ) = Right (x : xs)
parse xs (readMaybe -> Nothing) = Left "Syntax error"

您创建了两个独立的寻找目标类型的问题,每个问题对应 readMaybe。其中第一个的解决方法与 case 的情况相同,但对于第二个,请单独阅读,

parse xs (readMaybe -> Nothing) = Left "Syntax error"

根本不知道什么是你没看懂,也没有理由相信它和上面那行是一样的。

一般来说,除非只有一个感兴趣的结果,否则使用视图模式是不合适的。如果你想做一次中间计算一次,但将结果分析成不止一种情况,它们就是错误的语法。我很高兴保留记录,因为这个原因我认为它们是错误的。