split :: [a] -> Int -> ([a], [a])
split [xs] n =
(take n [xs], drop n [xs])
如果我将变量指定为xs
代替[xs]
,两种情况下的签名相同。使用[xs]
给出模式不详尽的错误。我知道这说明我提供的输入没有被我的代码覆盖,但不清楚幕后发生了什么。
测试输入:[1,2,3] 2
.
不知怎的,很多人认为[xs]
因为模式意味着你unify一个列表与xs
。但这是不正确的,因为函数签名(隐式派生或显式声明)已经会阻止您编写使用非列表项调用函数的代码。
一个列表有two构造函数:
- 空列表
[]
; and
- “缺点”
(h : t)
with h
the head(第一个元素),以及t
the tail(包含剩余元素的列表)。
然而 Haskell 也引入了一些语法糖。例如[1]
是缩写(1:[])
, and [1, 4, 2]
for (1:(4:(2:[])))
.
这意味着如果你写[xs]
,在幕后你定义了一个模式(xs: [])
这意味着您将所有列表与exactly一个元素,以及那个单一的element(不是整个列表)然后是xs
.
无论如何,解决方案是使用:
split xs n = (take n xs, drop n xs)
既然两者take :: Int -> [a] -> [a] http://hackage.haskell.org/package/base-4.10.1.0/docs/Prelude.html#v:take and drop :: Int -> [a] -> [a] http://hackage.haskell.org/package/base-4.10.1.0/docs/Prelude.html#v:drop签名中有xs
应该是一个列表,Haskell 会自动导出n
应该是一个Int
, and xs
an [a]
.
请注意,您可以使用splitAt :: Int -> [a] -> ([a], [a]) http://hackage.haskell.org/package/base-4.10.1.0/docs/Prelude.html#v:splitAt以及。我们可以使签名与您的目标签名相同:
split = flip splitAt
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)