如果我使用“[xs]",为什么这个功能不起作用?而不是“xs"? [英] Why doesn't this function work if I use "[xs]" instead of "xs"?

查看:31
本文介绍了如果我使用“[xs]",为什么这个功能不起作用?而不是“xs"?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

如果我将变量指定为 xs 而不是 [xs],则相同的代码有效,两种情况下的签名都相同.使用 [xs] 会给出模式不详尽的错误.我明白这说明我提供的输入没有包含在我的代码中,但不清楚幕后发生了什么.

The same code works if I give the variable as xs instead of [xs], signatures are same in both cases. Using [xs] gives the error that pattern is non-exhaustive. I understand it's telling that the input I gave is not covered by my code, but not clear what is happening under the hood.

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

推荐答案

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

Somehow a lot of people think that [xs] as pattern means that you unify a list with xs. But this is incorrect, since the function signature (either derived implicitly, or stated explicitly) already will prevent you to write code where you call the function with a non-list item.

一个列表有两个构造函数:

  • 空列表[];和
  • 缺点" (h : t)h head(第一个元素)和 t tail(包含剩余元素的列表).
  • the empty list []; and
  • the "cons" (h : t) with h the head (first element), and t the tail (a list with the remaining elements).

不过 Haskell 也引入了一些语法糖.例如 [1](1:[]) 的缩写,[1, 4, 2](1:(4:(2:[]))).

Haskell however introduces some syntactical sugar as well. For example [1] is short for (1:[]), and [1, 4, 2] for (1:(4:(2:[]))).

所以这意味着如果你写了 [xs],在幕后你定义了一个模式 (xs: []) 这意味着你匹配所有列表与 正好一个元素,而那个元素(不是整个列表)就是xs.

So that means that if you write [xs], behind the curtains you defined a pattern (xs: []) which thus means you match all lists with exactly one element, and that single element (not the entire list) is then xs.

反正解决方法是使用:

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

由于 采取 :: Int ->[a] ->[a]drop :: Int ->[a] ->[a] 在签名中有 xs 应该是一个列表,Haskell 会自动推导出 n 应该是成为Intxs成为[a].

Since both take :: Int -> [a] -> [a] and drop :: Int -> [a] -> [a] have in the signature that xs is supposed to be a list, Haskell will derive automatically that n is supposed to be an Int, and xs an [a].

请注意,您可以使用 splitAt :: Int ->[a] ->([a], [a]) 也是如此.我们可以使签名与您的目标签名相同:

Note that you can use splitAt :: Int -> [a] -> ([a], [a]) as well. We can make the signature equivalent to the one you target with:

split = flip splitAt

这篇关于如果我使用“[xs]",为什么这个功能不起作用?而不是“xs"?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆