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

Haskell非穷举模式与转换函数输出,haskell,Haskell,我有一个函数,它想列出所有数据类型 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 [] = []
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)]
它已编译,但当我调用该函数时,它再次告诉我“非穷举模式”。我正在努力思考我错过了什么模式,我应该在之后添加一个通配符模式来捕获所有内容吗?我不想找人把答案打出来,但欢迎提供提示或建议。

模式
[(f,r)]
仅在列表包含一个元素时匹配。如果它包含0、2或任何其他数字,则表示模式匹配失败

在这个例子中,代码应该做什么,我不能说…

模式
[(f,r)]
只在列表包含一个元素时匹配。如果它包含0、2或任何其他数字,则表示模式匹配失败


在本例中,代码应该做什么,我不能说…

您已经介绍了单元素列表的情况:它匹配
fn(dt@(数据类型tdy[(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)]
不过,这并不能解决您的问题,但它清楚地表明了发生了什么:显然,
数据类型tdy[(f,r)]
不是该类型的唯一有效模式。正如MathematicalArchid指出的,
[(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”)]
,那么您根本就没有真正使用一元绑定功能:您可以编写递归版本,而不必使用
++
,只需使用
重构对象,事实上,您只需执行一个
映射
操作:

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"

您已经介绍了单元素列表的情况:匹配
fn(dt@(数据类型tdy[(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)]
不过,这并不能解决您的问题,但它清楚地表明了发生了什么:显然,
数据类型tdy[(f,r)]
不是该类型的唯一有效模式。正如MathematicalArchid指出的,
[(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”)]
,那么您根本就没有真正使用一元绑定功能:您可以编写递归版本,而不必使用
++
,只需使用
重构对象,事实上,您只需执行一个
映射
操作:

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"

为什么指定为[(f,r)]的列表只包含一个元素?很好,我没有注意到这一点。考虑到该列表的内容与此特定功能不相关,用[u]替换它是否是一个合理的解决方案?@Chillo如果右侧不需要它,那么是的,那就行了。它出现了一个错误,但问题已经解决了!我添加了一行((f,r):rs),效果很好。尽管它们没有使用,但还是可以工作的,谢谢你的帮助。另外,你可以用一个
concat
和一个列表替换
++
s的负载-可能更容易阅读为什么指定为[(f,r)]的列表只包含一个元素?很好,我没有注意到这一点。考虑到该列表的内容与此特定功能不相关,用[u]替换它是否是一个合理的解决方案?@Chillo如果右侧不需要它,那么是的,那就行了。它出现了一个错误,但问题已经解决了!我添加了一行((f,r):rs),效果很好。尽管它们没有使用,但还是可以工作的,谢谢你的帮助。此外,你可以用一个
concat
和一个列表来替换
++
s的负载-阅读代码可能会更容易一些。代码会尝试将参数设置为
fn
,而
数据类型的最后一个参数总是
[(f,r)]
,它只匹配一个元素列表。修复了使((f,r):rs)即使不使用变量也能正常工作的问题。非常感谢。代码尝试将参数
fn
与几个不同的模式进行比较,但是
DataType
的最后一个参数始终是
[(f,r)]
,它只匹配一个元素列表。修复了使((f,r):rs)即使不使用变量也能正常工作的问题。非常感谢。非常有助于我找到解决问题的正确方法,感谢您的回复。非常有助于我找到解决问题的正确方法,感谢您的回复。