Home Articles

Haskell非穷举模式和转换函数输出

Asked
Viewed 444 times
1

我有一个想要列出所有 dataType 的函数 .

fn [] = []
fn (dt@(DataType t d y [(f,r)]):dts) = ["T:" ++ t ++ " D: " ++ d ++ " R: " ++ show y ++ "Ra" ++ show (fnAvg dt)] ++ fn dts

其中t和d是字符串,y是一个int,f是一个字符串,r是一个int(不确定f和r是否重要,将解释为什么) .

我得到错误非详尽的模式,并假设这是因为当列表中只有一个元素时我没有一个,所以我在其他模式之间添加了这个:

fn [dt@(DataType t d y [(f,r)])] = ["T:" ++ t ++ " D: " ++ d ++ " R: " ++ show y ++ "Ra" ++ show (fnAvg dt)]

它编译了,但是当我调用它时,它再一次告诉我'非详尽的模式' . 我很难想到我错过了什么样的模式,我是否应该在之后添加一个通配符模式以捕获所有内容?我不是在找人写出答案,但欢迎提示或建议 .

2 Answers

  • 5

    你已经覆盖了one-element-list的情况:匹配 fn (dt@(DataType t d y [(f,r)]):[]) ,因为 dts 可以是包括空列表在内的任何东西 .

    事实上,没有理由在这里使用显式递归:你基本上有类似的东西

    f [] = []
    f (x:xs) = g x ++ f xs
    

    将其与列表的monad实例进行比较:

    instance Monad [] where
      return x = [x]
      [] >>= _ = []
      (x:xs) >>= g = g x ++ (xs >>= g)
    

    所以你应该把你的功能写成

    fn l = l >>= \dt@( DataType t d y [(f,r)] ) 
        -> ["T:" ++ t ++ " D: " ++ d ++ " R: " ++ show y ++ "Ra" ++ show (fnAvg dt)]
    

    这赢得了't fix your problem though, but it makes it obvious what':显然, DataType t d y [(f,r)] 并不是该类型的唯一有效模式 . 正如MathematicalOrchid指出的那样, [(f,r)] 仅匹配长度为1的列表,但您还需要覆盖其他长度 .

    fn l = l >>= \dt -> case dt of
       DataType t d y [(f,r)]
        -> ["T:" ++ t ++ " D: " ++ d ++ " R: " ++ show y ++ "Ra" ++ show (fnAvg dt)]
       DataType t d y []
        -> ["Some other stuff"]
       DataType t d y [(f,r), ...]
        -> ["Yet other stuff"]
    

    管他呢 .

    实际上,如果你只是在这里返回 [ ("stuff") ] ,那么你根本就没有真正使用monadic绑定功能:你可以编写没有 ++ 的递归版本,只用 : 重建东西,实际上你只需要一个 map 操作:

    fn = map $ \dt -> case dt of
       DataType t d y [(f,r)]
        -> "T:" ++ t ++ " D: " ++ d ++ " R: " ++ show y ++ "Ra" ++ show (fnAvg dt)
       DataType t d y []
        -> "Some other stuff"
       DataType t d y [(f,r), ...]
        -> "Yet other stuff"
    
  • 4

    仅当列表包含一个元素时,模式 [(f,r)] 才匹配 . 如果它包含零个,或两个或任何其他数字,则表明模式匹配失败 .

    在这种情况下代码应该做什么,我不能说......

Related