List 如何修复代码中的错误(';无法构造无限类型';),以及如何使代码正常工作
基本上,我试着做一个函数,给你一个列表和一个数字,你必须把列表分割成与给定数字相同大小的列表,最后一次分割的长度可以小于给定的数字List 如何修复代码中的错误(';无法构造无限类型';),以及如何使代码正常工作,list,haskell,List,Haskell,基本上,我试着做一个函数,给你一个列表和一个数字,你必须把列表分割成与给定数字相同大小的列表,最后一次分割的长度可以小于给定的数字 separa a xs = if length xs >= a then separaM a (drop a xs) ([take a xs]) else [xs] separaM a xs yss = if length xs >= a then separaM a (drop a xs) (yss : (take a xs)) else separ
separa a xs = if length xs >= a then separaM a (drop a xs) ([take a xs]) else [xs]
separaM a xs yss = if length xs >= a then separaM a (drop a xs) (yss : (take a xs)) else separaM a [] (yss : xs)
separaM a [] yss = yss
我希望3个“comovais”的输出为[“com”、“ova”、“is”],但在我的程序中,由于错误而没有输出您的代码中有一些错误。调整对
(:)
的误用,使其通过类型检查:
separa a xs
| length xs >= a = go a (drop a xs) [take a xs]
| otherwise = [xs]
where
go a xs yss
| length xs >= a = go a (drop a xs) (yss ++ [take a xs])
-- was: (yss : (take a xs))
| otherwise = go a [] (yss ++ [xs])
-- was: (yss : xs)
go a [] yss = yss
但最好进一步改为
separa :: Int -> [a] -> [[a]]
separa a xs
| length xs >= a = go a (drop a xs) [take a xs]
| otherwise = [xs]
where
go a xs yss
| length xs >= a = go a (drop a xs) ([take a xs] ++ yss)
| otherwise = reverse ([xs] ++ yss)
它的工作原理是:
> separa 3 [1..10]
[[1,2,3],[4,5,6],[7,8,9],[10]]
这是一种常见的“反向构建,然后在构建时反向构建”的习惯用法,在严格的函数式语言中很常见。其中一些允许通过称为尾部递归模cons的技术,以自顶向下的自然顺序构建列表。Haskell是懒惰的,它让我们以自上而下的方式自然轻松地构建它的列表,并使用等效的保护递归:
这里有一个由一个关闭的错误;我把它留给你自己解决
但有时无限类型是问题固有的,而不是编程错误的结果。然后我们可以通过使用递归类型来修复它 每当我们得到类型等价性
t~a..b..t..c..
,我们就可以从定义类型开始
newtype T = MkT (a..b..T..c..)
然后查看哪些类型变量是自由的,并关闭它们,如图所示
newtype T a b c = MkT (a..b..(T a b c)..c..)
例如:请注意表达式:
yss : (take a xs)
(以xs为例)
具有类型[b]
,因此yss
具有类型b
。但是当您将yss:(使用xs)
作为separaM
函数的参数传递时,yss
应具有类型[b]
而不是b
。这就是发生错误的原因
实际上,您不需要yss
来存储结果,递归函数可以定义为:
separaM _ [] = []
separaM a xs = (if length xs >= a then (take a xs) else xs) :
separaM a (drop a xs)
separaM _ [] = []
separaM a xs = (if length xs >= a then (take a xs) else xs) :
separaM a (drop a xs)