我已设法实现模拟过滤器功能(经过多次尝试)
filter' :: (Num a, Eq a) => (a -> Bool) -> [a] -> [a]
filter' a [] = []
filter' a (x:xs) = if a x
then x : filter' a xs
else filter' a xs
Run Code Online (Sandbox Code Playgroud)
我不清楚的是类型声明
filter' :: (Num a, Eq a) => (a -> Bool) -> [a] -> [a]
-- filter' (<10) [1,2,3]
-- output = []
Run Code Online (Sandbox Code Playgroud)
我们传入(<10) [1,2,3].但是在类型声明中,(a -> Bool)我们传递一个来自列表的递归,输出为true或false.然而,表达测试(<10)?怎么样我们为什么不添加另一个Bool?
你的filter'函数类型只是如此受限制,因为你已经声明它是.如果您没有声明类型,编译器将推断出更宽容的类型:(a -> Bool) -> [a] -> [a].这与内置filter函数的类型相同:
Prelude> :type filter
filter :: (a -> Bool) -> [a] -> [a]
Run Code Online (Sandbox Code Playgroud)
表达式(< 10)是所谓的部分.这是部分应用的功能.
运营商<本身就是一个功能:
Prelude> :type (<)
(<) :: Ord a => a -> a -> Bool
Run Code Online (Sandbox Code Playgroud)
您可以将其读作:<是一个带有两个参数的函数,两个参数都是泛型类型a.该类型a必须属于类型类Ord.<使用这两个值调用时,将Bool返回一个值.
由于Haskell函数是curry,你可以只用一些参数调用一个函数.返回值是一个"等待剩余参数"的新函数:
Prelude> :type (< 10)
(< 10) :: (Num a, Ord a) => a -> Bool
Run Code Online (Sandbox Code Playgroud)
这种类型有点受限制,因为10推断文字属于Num类型类.由于<正在使用,该(Ord)的原始约束仍然有效.
表达式[1,2,3]是由编译器推断为:
Prelude> :type [1,2,3]
[1,2,3] :: Num t => [t]
Run Code Online (Sandbox Code Playgroud)
这些值都属于Num类型类.当您同时使用所有这些类型时,您将获得所有推断类型的并集:
Prelude> :type filter (< 10) [1,2,3]
filter (< 10) [1,2,3] :: (Num a, Ord a) => [a]
Run Code Online (Sandbox Code Playgroud)
该Num类型类的推断,因为文字的使用,而Ord类型类是因为使用的推断<运营商.