【问题标题】:Pattern matching on wild card通配符上的模式匹配
【发布时间】:2019-03-19 22:28:19
【问题描述】:

您好,我正在尝试对 通配符 模式进行模式匹配,但我需要“获取”wild card。我正在尝试将 String 解析为 @ 的 list 987654324@.

输入
{123,aa,55,66}
输出
[Just 123,Nothing,Just 55.4,Just 66.3]

所以我把方法如下:

方法

readDataRaw::String->[Maybe Int]
    readDataRaw (x:xs)=go [] [](x:xs) where
            go _ ls []         = ls
            go small big (x:xs)= case x of
                                  '}'    -> big
                                  ','    -> go [] ((readMaybe small::Maybe Int):big)  xs 
                                   c@(_) -> go [] c:small big xs

错误

parse error on input `->'
   |
66 |                                    c@(_) -> go [] c:small big xs
   |                                          ^^

在我的最后一种情况下,如何使用 -> 右侧的通配符?

【问题讨论】:

  • 虽然您应该使用模式c 而不是c@(_),但后者没有任何问题。上面代码中真正的问题是c@(_)没有缩进为上一行的',',所以被解析为上一行的延续,就好像你写了一行',' -> go [] (....) xs c@(_) -> go [] ...

标签: haskell pattern-matching wildcard


【解决方案1】:

你可以只使用一个变量标识符,一个变量不指定任何模式,所以你可以这样写:

readDataRaw::String -> [Maybe Int]
readDataRaw (x:xs) = go [] [](x:xs) where
    go _ ls [] = ls
    go small big (x:xs) = case x of
        '}' -> big
        ',' -> go [] ((readMaybe small::Maybe Int):big)  xs 
        c -> go [] c:small big xs

然而,上面有一些错误和不完整的模式。例如,在readDataRaw 中,您只需在头部指定(x:xs) 模式,而严格来说,您可以使用空列表[] 调用该函数。它还与go 模式中的(x:xs)“冲突”:这不是问题,因为Haskell 采用“最接近”的变量,所以定义在go 子句中的变量,但它引入了一些混淆。在最后一种情况下(使用c,您还返回go [] c : small big xs,这将被解释为(go [] c) : small big xs,这没有多大意义。“重构”实现可能如下所示:

readDataRaw::String -> [Maybe Int]
readDataRaw = go [] [] where
    go _ ls [] = ls
    go small big (x:xs) = case x of
        '}' -> big
        ',' -> go [] ((readMaybe small::Maybe Int):big)  xs 
        c -> go (c:small) big xs

不过,还是有点“丑”。这部分是因为不清楚你想做什么

【讨论】:

  • @BercoviciAdrian:66.3Int 怎么样?
  • 这看起来像是一个经典问题:你的目标是在一个函数中做太多事情。您可以制作一个省略大括号的解析器,并用逗号分割输入,接下来它只是一个mapping 和readMaybe
  • 我很抱歉这是一个错字,它是Int 还是Double 真的没关系。最初我想做一些可以在更多类型上工作的东西..但我让它Int.
  • @BercoviciAdrian:说得好,我认为使用Parsec (hackage.haskell.org/package/parsec) 之类的工具可能会更好地指定您的语言的“语法”,从而省略大括号,并用逗号分隔。然后,您可以对任何类型执行简单的map readMaybe
  • @BercoviciAdrian:是的,但那是你指定数据构造函数的时候,所以是variablename@(constructor para meters)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多