如果我使用" [xs]"为什么这个功能不起作用?而不是" xs"?

时间:2018-02-20 11:27:58

标签: haskell

split :: [a] -> Int -> ([a], [a])
split [xs] n = 
    (take n [xs], drop n [xs])

如果我将变量设为xs而不是[xs],则相同的代码有效,两种情况下的签名都相同。使用[xs]会产生错误,即模式并非详尽无遗。我理解它告诉我,我提供的输入不在我的代码中,但不清楚幕后发生了什么。

测试输入:[1,2,3] 2

1 个答案:

答案 0 :(得分:10)

不知何故,很多人认为[xs]作为模式意味着您统一列表xs。但这是不正确的,因为函数签名(隐式派生或明确说明)已经阻止您编写使用非列表项调用函数的代码。

列表中有两个构造函数:

  • 空列表[];和
  • &#34; cons&#34; (h : t) h head (第一个元素),t tail (包含其余元素的列表)。< / LI>
然而,Haskell也引入了一些语法糖。例如,[1](1:[])的缩写,[1, 4, 2](1:(4:(2:[])))的缩写。

这意味着如果你写下[xs],在窗帘后面你定义了一个模式(xs: []),这意味着你匹配所有列表完全一个元素,那个单一元素(不是整个列表)是xs

无论如何,解决方案是使用:

split xs n = (take n xs, drop n xs)

由于take :: Int -> [a] -> [a]drop :: Int -> [a] -> [a]都在签名中xs应该是一个列表,Haskell会自动导出n应该是Int 1}},xs[a]

请注意,您也可以使用splitAt :: Int -> [a] -> ([a], [a])。我们可以使签名等同于您目标的签名:

split = flip splitAt