[英]How do you pass list in a function parameter in haskell?
我知道这个问题以前已经被问过很多次了,我已经仔细阅读了,但并不能帮助我回答这类问题。 我是Haskell的新手,
假设我们有以下内容:
filter p [] = []
filter p (h:l) = if (p h) then (h:(filter p l)) else (filter p l)
如何调用过滤器? 我所知道的是,您通过了p
,这是一个列表
老实说,我一般不知道什么是多态类型,而且我无法弄清楚过滤器函数的多态类型。
我不了解if语句中函数过滤器的作用。
如果您能在这两个问题上协助我,我将不胜感激。
有很多资源可以解释多态性,但是我不理解它们。
p
不是列表。 p
是谓词的缩写,通常是指带值并返回Bool
的函数的术语。 列表是filter
的第二个参数。
您如何称呼过滤器? 您需要阅读许多haskell书籍之一。 马上。 一些例子:
filter (> 5) [1, 6, 2, 8, 9, 3] -- [6, 8, 9]
filter (== 'z') "bazzz" -- "zzz" (String === [Char])
这里(> 5) :: Int -> Bool
和(== 'z') :: Char -> Bool
是谓词。
多态非常松散地表示不同类型的形式相同:
filter :: (a -> Bool) -> [a] -> [a]
filter
必须适用于任何类型a
。 因此,特定的a
对实现者是未知的,并且该函数无法假定有关a
任何信息。 a
是通过在调用位置的函数的用户选择。
顺便说一句。 弄清楚允许执行以下功能是一个有趣的小练习:
:: a -> a
(提示:它只能做一件事,名字就给它了,所以我省略了)
你也能想到的filter
作为函数族所实施完全相同,只是在不同的a
。 其中一些可能是:
:: (Int -> Bool) -> [Int] -> [Int]
:: (Char -> Bool) -> [Char] -> [Char]
:: (Foo -> Bool) -> [Foo] -> [Foo]
在学习新概念时,SO并不是一个很好的起点。 你真的应该抓一本好书。
在深入了解实现之前,我们应该确定filter
的类型。 实际上,您通常应该设计函数的类型签名,而无需编写任何实际代码……但是损坏已经在这里完成了。 (谨此陈辞,您现在可以实际询问GHCi 您的实现的类型是什么……但是同样,这是倒退的,所以我不会深入研究它。)
那么,您希望filter
完成什么工作? 确实应该列出一个清单。 您想根据每个元素可能具有的某些属性来提取该列表中的某些元素。 但是filter
不应该有任何难以理解的假设,即要使用什么条件,即应该是任何元素类型的列表的类型 。 在Haskell中,我们将其写为[a]
(实际上是∀ a . [a]
简写,请读成“对于您可能考虑的所有元素类型-例如A
–这是[A]
类型的列表”)。
然后,应通过一个额外的参数确定实际标准是什么: 过滤谓词 。 例如,您可能要从整数列表中过滤所有小于5
数字–您可以使用谓词(<5) :: Int -> Bool
。 通常,对于您的[a]
列表,您需要使用a- a -> Bool
类型a -> Bool
谓词。 最终结果将具有与您传入时相同的列表元素,因此filter
将具有签名
filter :: [a] -> (a -> Bool) -> [a]
...除约定外,我们将谓词放在首位,即
filter :: (a -> Bool) -> [a] -> [a]
让我们检查一下这是有道理的...例如,我们想要
> filter ((<5) :: Int -> Bool) ([4,9,3] :: [Int])
在这种情况下a ~ Int
filter :: (Int -> Bool) -> [Int] -> [Int]
...是的,这很有意义。
现在,您实际上开始担心实现了。 有两种通用方法:
解构列表。 基本上,列表只能有两种显示方式:它可以包含某些内容,也可以为空。 空很容易,因为在这种情况下,您只能返回一个空列表,而不能返回其他任何内容。 你甚至不能使用谓词,因为没有你可以用它检查元素,因此仅仅通过匹配丢弃_
:
filter _ [] = []
(或者,您也可以将谓词匹配为p
,但是人们会怀疑:发生了什么 鼠标 p
?)
如果列表不为空,则可以从其中直接弹出一个元素:
filter p (h:l) = …
在这里, h
是头元素, l
是列表的其余部分。 太好了,我们现在有了一个类型a
的元素,让我们看看谓词告诉我们的内容!
filter p (h:l) = if ph then … else …
因此,如果谓词得到满足,我们希望在最终结果中再次看到h
,不是吗? 实际上,最终结果应以h
开头
filter p (h:l) = if ph then h : … else …
最终结果的其余部分应与输入列表的其余部分有关。 我们可以照原样传递then h : l else …
,但这意味着我们只能控制head元素的条件。 不,我们仍然必须过滤列表的其余部分:
filter p (h:l) = if ph then h : filter pl else …
实际上,即使谓词没有满足h
,我们也想这样做,除非我们不添加它:
filter p (h:l) = if ph then h : filter pl else filter pl
然后你去了:
filter _ [] = []
filter p (h:l) = if p h then h : filter p l else filter p l
if
看起来有些笨拙,则首选语法实际上是警卫 (它们执行相同的操作)
filter _ [] = []
filter p (h:l)
| p h = h : filter p l
| otherwise = filter p l
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.