函数返回列表的一部分

时间:2017-04-09 00:16:22

标签: function haskell syntax

我是Haskell的新手并且有一个任务。我必须写一个

  

内部>内部 - > [U] - > [U]

给定输入两个I和i以及一个列表的函数,并返回大于i且小于j的位置的元素。到目前为止我所想的是:

fromTo :: Int->Int->[u]->[u]
fromTo i j (h:t) 
    |i == 1 && j == length(h:t)
        = (h:t)
|i /= 1
    fromTo (i-1) j t
|j /= length(h:t)
    fromTo i j init(h:t)

但是我得到了第二个语法错误。我也不确定我的思路是否正确。 (init返回没有最后一个元素的列表)

编辑:已更正

|i /= 1
    fromTo (i-1) j (h:t)

|i /= 1
    fromTo (i-1) j t

3 个答案:

答案 0 :(得分:2)

修正缩进,括号和缺少=。这个改革编译,并适用于序数和有限的非空列表:

fromTo :: Int -> Int -> [u] -> [u]
fromTo i j (h : t)
   | i == 1 && j == length (h : t) = h : t
   | i /= 1                        = fromTo (i - 1) j t
   | j /= length (h : t)           = fromTo i j (init (h : t))

我认为你正在寻找类似这样的东西,自然地索引span

take :: Int -> [a] -> [a]
take _ []       = []
take 0 _        = []
take n (x : xs) = x : take (n - 1) xs

drop :: Int -> [a] -> [a]
drop _ []       = []
drop 0 xs       = xs
drop n (_ : xs) = drop (n - 1) xs

span :: Int -> Int -> [a] -> [a]
span i j  =  drop i . take (j + 1)

其中

span 0 3 [0 .. 10]  ==  [0,1,2,3]

或者,为了符合规范:

between :: Int -> Int -> [a] -> [a]
between i j  =  drop (i + 1) . take j

其中

between 0 3 [0 .. 10]  ==  [1,2]

答案 1 :(得分:0)

您在=保护条款与正文之间缺少|。 Haskell编译器认为整个事情都是守护者,当它遇到下一个|后卫时会感到困惑,因为它首先需要一个身体。这将编译(虽然它仍然是错误的):

fromTo :: Int -> Int -> [u] -> [u]
fromTo i j (h:t) 
  | i == 1 && j == length (h:t) =
    (h:t)
  | i /= 1 =
    fromTo (i-1) j t
  | j /= length (h:t) =
    fromTo i j (init (h:t))

但我想说有更好的方法来编写这个功能。例如,原则上这样的函数应该在无限列表中起作用,但是使用length使得这是不可能的。

答案 2 :(得分:0)

以下是使用递归的完整解决方案:

fromTo :: Int -> Int -> [u] -> [u]
fromTo i j xs = go i j xs []
    where go i j (x:xs) rs
        | i < 0 || j < 0 = []
        | i > length (x:xs) || j > length (x:xs) = []
        | i /= 0                        = go (i - 1) j t
        | j /= 1           = goo i (j -1) (rs ++ [x])
        | otherwise = rs

注意: go是递归函数的标准Haskell习惯用法,与主级函数相比需要额外的参数。 第一个子句确保负索引导致空列表。对于超过列表大小的任何索引,第二个都是相同的。 列表必须是有限的。第三个&#34;忘记&#34;阵列的头部i次。第四个将积累&#34; next&#34; (j - 1)进入rs。当所有索引都花费在&#34;&#34;并且rs包含结果。

你可以让它在无限列表上工作。删除第二个条款。如果rs为空,则退回xs&#34;耗尽&#34;索引。然后功能将采取&#34;直到&#34;来自(j-1)的{​​{1}}元素。