解释这个haskell功能“要列出的元组列表”

时间:2018-05-21 09:41:51

标签: haskell

我是初学者,基本上我需要this

的解释

他回答这段代码:

tupleToList :: [(a,a)] -> [a]
tupleToList ((a,b):xs) = a : b : tupleToList xs
tupleToList _          = []

但我不会暗示他为什么不使用:

tupleToList [] = []
tupleToList ((a,b):xs) = a : b : tupleToList xs
像我通常在导游的第一次练习中看到的一样。 我知道'_'是什么,但是,当列表为空时,使用'[]'是不是更好?

2 个答案:

答案 0 :(得分:9)

  像我通常在导游的第一次练习中看到的一样。我知道#!groovy DOCKER_IMAGES = ["python:3.5.0", "python:3.6.5"] def get_stages(docker_image) { stages = { docker.image(docker_image).inside { // The following line causes a weird issue, where pip tries to // install into /usr/local/... instead of the virtual env. // Any help figuring out what's happening is appreciated. // // def PYTHON_VENV = docker_image.replaceAll('[:.]', '') + 'venv' // // So we set it to 'venv' for all parallel builds now def PYTHON_VENV = 'venv' withEnv(["HOME=${env.WORKSPACE}"]){ stage("${docker_image}") { echo "Running in ${docker_image}" } stage("Prepare") { sh "echo 'Home is set to:' $HOME" sh "echo 'Workspace is:' ${env.WORKSPACE}" sh "rm -rf ${PYTHON_VENV}" sh "python -m venv ${PYTHON_VENV}" sh """ . ${PYTHON_VENV}/bin/activate pip install -U pip setuptools wheel """ } } } } return stages } node('master') { cleanWs() def stages = [:] for (int i = 0; i < DOCKER_IMAGES.size(); i++) { def docker_image = DOCKER_IMAGES[i] stages[docker_image] = get_stages(docker_image) } parallel stages } 是什么,但是,当列表为空时,使用_是不是更好?

从语义上讲,两者是相同的,因为2元组只有一个构造函数[],而列表有两个构造函数(a,b)[]

由于第一个子句唯一不匹配的模式是空列表,通配符 (h:t)等同于_

由于[][]析取模式(即没有可以匹配这两种模式的值),因此两种模式的顺序并不重要明确使用((a,b):xs)。我们可以按照我们喜欢的任何顺序编写它。

一些Haskell程序员更喜欢使用显式模式(因此使用[]而不是[]),因为这意味着我们知道我们实际使用该子句处理哪些值。如果以后Haskell社区决定引入一个额外的列表构造函数(是的,对于非常不可能的列表,但对于其他_类型,这可能更合理),Haskell编译器可以(使用data )发出警告,说明某些模式未被涵盖。通配符当然涵盖所有模式,但右边的表达式可能不是我们为附加构造函数设计的那个。

因此,如果您希望通过相同的子句匹配多个模式,我建议仅使用通配符 。如果清楚其他模式是什么,最好是明确的。就像 Python的所说的那样(是的,它是Python,但大多数概念在某种程度上是通用的):&#34; 显式优于隐式&#34;

答案 1 :(得分:5)

没有区别:它们的语义完全相同。

tupleToList [] = []
tupleToList ((a,b):xs) = a : b : tupleToList xs

相当于

tupleToList ((a,b):xs) = a : b : tupleToList xs
tupleToList [] = []

相当于

tupleToList ((a,b):xs) = a : b : tupleToList xs
tupleToList _ = []

通常,当我们需要模式匹配多个案例时,使用通配符_。 E.g。

myAnd :: Bool -> Bool -> Bool
myAnd True  y = y
myAnd False _ = False

上面,我们可以单独枚举False FalseFalse True个案例,并使用三个等式,但使用通配符更方便(并使我们的函数稍微更懒,例如myAnd False undefined评估到False)。

结论,这主要是风格问题。通常情况下,当通配符_只能代表一个案例时, 更好地将其拼写出来,以明确它。通过这种方式,代码通常更具可读性。 E.g。

not :: Bool -> Bool
not False = True
not _     = False

等同于

not :: Bool -> Bool
not False = True
not True  = False

当然,case表达也是如此。

case x of
  Just y  -> 1 + y
  Nothing -> 0

可以说比

更具可读性
case x of
  Just y -> 1 + y
  _      -> 0