Idris> :t (++)
Prelude.List.(++) : List a -> List a -> List a
这是编译器不能确定的a
值。如果您只需在REPL中键入[1,2,3]
,则会给它List Integer
的类型。但[1,2,3]
也可能是List Int
,List Nat
或某些数字的任何其他列表类型。如果你尝试用['a','b','c']
你的榜样,这种不确定性消失和REPL会很乐意接受它:
Idris> zipWith (\xs, ys => xs ++ ys) [['a'],['b'],['c']] [['a'],['b'],['c']]
[['a', 'a'], ['b', 'b'], ['c', 'c']] : List (List Char)
您可以通过给类型检查提供信息解决最初的问题:
zipWith (\xs, ys => (++) xs ys {a=Integer}) [[1],[2],[3]] [[4],[5],[6]]
zipWith (\xs, ys => the (List Integer) (xs ++ ys)) [[1],[2],[3]] [[4],[5],[6]]
the (List (List Integer)) (zipWith (\xs, ys => xs ++ ys) [[1],[2],[3]] [[4],[5],[6]])
在大多数但最简单的情况是统一需要一些类型的声明。这就是为什么(++)
有效,但不是lambda表达式。前者更容易,后者更具抽象性(即额外的功能)。
但在文件中写入实际代码时,编译器会不会像REPL友好反正会要求一个类型声明:
-- test : List (List Integer)
test = zipWith (\xs, ys => xs ++ ys) [[1],[2],[3]] [[4],[5],[6]]
Type checking ./test.idr
test.idr:1:1:No type declaration for Main.test