基本上我正在尝试执行一个函数,在该函数中给您一个列表和一个数字,并且您必须将列表拆分成与给定数字大小相同的列表,并且所有最后一次拆分的长度都可以小于给出的数字
b
我希望3个“ comovais”的输出为[“ com”,“ ova”,“ is”],但是由于错误,在我的程序中没有输出
答案 0 :(得分:6)
请注意表达式:
yss : (take a xs)
(take a xs)
的类型为[b]
,因此yss
的类型为b
。但是,当您将yss : (take a 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)
答案 1 :(得分:3)
Your code has some errors in it. Tweaking your misuse of (:)
gets it to pass the type-checker:
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
but it's better to further change it to
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)
It works:
> separa 3 [1..10]
[[1,2,3],[4,5,6],[7,8,9],[10]]
This is a common "build in reverse, then reverse when built" idiom, frequently seen in strict functional languages. Some of them allow for lists to be built in top-down, natural order, by a technique known as tail-recursion modulo cons. Haskell is lazy, and lets us build its lists in top-down manner naturally and easily, with the equivalent guarded recursion:
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) (yss ++ [take a xs])
yss ++ go a (drop a xs) [take a xs]
| otherwise = -- go a [] (yss ++ [xs])
yss ++ [xs]
There's an off-by-one error here; I'll leave it for you to fix on your own.
But sometimes the infinite type is inherent to a problem, and not a result of a programming error. Then we can fix it by using recursive types.
Whenever we get type equivalency t ~ a..b..t..c..
, we can start by defining a type
newtype T = MkT (a..b..T..c..)
then see which type variables are free and close over them, as
newtype T a b c = MkT (a..b..(T a b c)..c..)
An example: Infinite type error when defining zip with foldr only; can it be fixed?