Haskell 如何制作自定义过滤器?

Haskell 如何制作自定义过滤器?,haskell,filter,Haskell,Filter,我自己很难弄明白这一点,但没有成功。我试图制作自己的过滤器,而不是不包括在列表中的东西,因为它是假的,它做了一些事情 代码 我所尝试的: myfilter :: (a -> Bool) -> [a] -> [a] myfilter p (x:xs) | p x = x : myfilter p xs | otherwise = []:myfilter p xs 例如,我试图让myFilter在输出列表中添加一个空白[] myFilter isIt1andOnly1[[1]

我自己很难弄明白这一点,但没有成功。我试图制作自己的过滤器,而不是不包括在列表中的东西,因为它是假的,它做了一些事情

代码 我所尝试的:

myfilter :: (a -> Bool) -> [a] -> [a]
myfilter p (x:xs)
 | p x = x : myfilter p xs
 | otherwise = []:myfilter p xs
例如,我试图让myFilter在输出列表中添加一个空白[]

myFilter isIt1andOnly1[[1],[2,2],[3,4]]])
输出 输出应该是什么:

[[1], [ ], [ ], []]
内置过滤器的作用:

[[1]]
非常感谢您的帮助

编辑: 对不起,我造成了误会,但我不是在找你

filter (==1) [list] 
将问题稍微更改为关于自定义筛选器而不是筛选器==1[[randomlist]]的问题更具体一些。

myfilter是正确的。和filter一样,它所做的只是过滤一个列表:它传递一些元素,而不传递一些元素,但它从不更改任何元素

然而,您建议在结果中包含不在原始列表中的元素。这不能用过滤器来完成。但是,您还有一个常量:您永远不会更改外部列表的结构。所以,这是map的任务。进行筛选的位置在内部列表上,因此需要将筛选映射到外部列表上。多亏了咖喱,这在哈斯凯尔非常容易:

Prelude> map (filter isItOne) [[1],[2],[3],[1]]
[[1],[],[],[1]]
在这里,isItOne必须具有签名Integer->Bool:它只对内部列表的单个元素有效,而不是对整个内部列表有效。这就是你实现的

写isItOne的两种更好的方法:

事实上,您不妨将以下内容内联:

Prelude> map (filter (==1)) [[1],[2],[3],[1]]
[[1],[],[],[1]]
myfilter不知道它正在处理列表列表。查看您给myfilter的类型签名:

[a] 指任意类型a的列表;myfilter对a一无所知。所以在另一个分支中,类型检查器认为您试图输出一个空列表,但我不确定a实际上是一个列表

解决此问题的一种方法是调整类型签名,使其更具体地说明我们正在使用嵌套列表:

myfilter :: ([a] -> Bool) -> [[a]] -> [[a]]
这段代码的另一个问题是,当输入列表为空时,您忘记了处理这个案例。您需要添加一个与空列表匹配的子句:

myfilter p [] = []

通过这些编辑-我认为该函数的工作方式应该有所不同,但首先要解决您的问题

myfilter :: (a -> Bool) -> [[a]] -> [[a]]
myfilter _ []                   = [ ]
myfilter p ([x]:xs) | p x       = [x]: myfilter p xs
                    | otherwise = [ ]: myfilter p xs
myfilter p ( _ :xs)             = [ ]:myfilter p xs
但是在这个函数中包含寻找单例列表的逻辑有点笨拙。我宁愿写一些像monoidalFilter的东西——这是我刚刚发明的一个术语。幺半群是允许串接/加法/乘法的东西,它有一个中性元素,比如零或一

monoidalFilter :: Monoid m :: (m -> Bool) -> [m] -> [m]
monoidalFilter p = map (\x -> if p x then x else mempty)
然后monoidalFilter==[1]将实现这一技巧

> ghci tst.hs
GHCi, version 7.10.3: http://www.haskell.org/ghc/  :? for help
[1 of 1] Compiling Main             ( tst.hs, interpreted )
Ok, modules loaded: Main.
*Main> monoidalFilter (==[1]) [[],[1],[1,1],[2,2]]
[[],[1],[],[]]
*Main> myfilter (==1) [[],[1],[1,1],[2,2]]
[[],[1],[],[]]

一个解决方案是使用map filter==1这将产生给定输入的结果,并尝试从那里返回,最好从类型signature开始[[],[1],[1,1],[1,2]]的预期结果是什么也许我应该改写我的问题,我一般都这么做了,这样更容易理解,我只想过滤器做一些事情,如果它是假的,如果它是真的
monoidalFilter :: Monoid m :: (m -> Bool) -> [m] -> [m]
monoidalFilter p = map (\x -> if p x then x else mempty)
> ghci tst.hs
GHCi, version 7.10.3: http://www.haskell.org/ghc/  :? for help
[1 of 1] Compiling Main             ( tst.hs, interpreted )
Ok, modules loaded: Main.
*Main> monoidalFilter (==[1]) [[],[1],[1,1],[2,2]]
[[],[1],[],[]]
*Main> myfilter (==1) [[],[1],[1,1],[2,2]]
[[],[1],[],[]]