涉足伊德里斯,我试图将this Haskell function移到伊德里斯。我想我用这段代码成功了......
windowl : Nat -> List a -> List (List a)
windowl size = loop
where
loop xs = case List.splitAt size xs of
(ys, []) => if length ys == size then [ys] else []
(ys, _) => ys :: loop (drop 1 xs)
但是,当我在交互式idris中调用它时,似乎只评估了对函数的第一次调用,递归的下一步不是。这是我在控制台上得到的。
*hello> windowl 2 [1,2,3,4,5]
[1, 2] :: Main.windowl, loop Integer 2 [2, 3, 4, 5] : List (List Integer)
有人可以告诉我发生了什么以及如何完全评估这个功能吗?
答案 0 :(得分:4)
正如manual:
中所述在编译时,它[Idris]只会评估它知道的全部内容 ...... [跳过] ...... 为方便起见,REPL使用编译时的评估概念。
整体检查程序无法发现windowl
函数实际上是总数,因此我们可以使用assert_smaller
construction作弊:
total
windowl : Nat -> List a -> List (List a)
windowl size = loop
where
loop : List a -> List (List a)
loop xs = case List.splitAt size xs of
(ys, []) => if length ys == size then [ys] else []
(ys, _) => ys :: loop (assert_smaller xs $ drop 1 xs)
或更改loop
以使整体检查器显而易见:
total
windowl : Nat -> List a -> List (List a)
windowl size = loop
where
loop : List a -> List (List a)
loop [] = []
loop xs@(x :: xs') = case List.splitAt size xs of
(ys, []) => if length ys == size then [ys] else []
(ys, _) => ys :: loop xs'
是的,我在这里偷工减料,用模式匹配替换硬编码的drop 1
来说明这个想法。更一般的情况可能需要更多的工作。
此时,REPL完全评估表达式:
λΠ> windowl 2 [1,2,3,4,5]
[[1, 2], [2, 3], [3, 4], [4, 5]] : List (List Integer)