我是haskell的新手,我读了一些关于这个称为类型签名的东西,但有一些我不理解的东西.
这是我正在看的代码:
--mult applies product
mult :: Num a => [a] -> a
mult = foldr (*) 1
--posList filters positive numbers out
posList :: (Ord a, Num a) => [a] -> [a]
posList = filter (>0)
--trueList determines whether all of the members of a list are T or not
trueList :: [Bool] -> Bool
trueList = foldr(&&) True
--evenList determines where all of the members of a list are even or not
evenList :: (Integral a, Foldable t) => t a -> Bool
evenList x = if (((foldr (+) 2 x ) `mod` 2) == 0) then True else False
Run Code Online (Sandbox Code Playgroud)
所以,我知道你可以用不同的方式做的那些功能更容易,但我不得不分配使用高阶函数map,filter并且foldr,所以我不得不做他们的方式.无论如何,我理解函数是如何工作的,因为我是编写它们的人,我不理解那些术语Integral,Foldable它们是什么意思?他们用Haskell称之为什么?
这些是多态类型的约束.
Haskell尽管是静态类型的,但通过称为参数多态的系统,可以很容易地编写可以使用不同类型的函数.我将首先为您的所有函数提供具体(单态)签名:
mult :: [Integer] -> Integer
mult = foldl' (*) 1 -- foldl' is better for performance/memory than foldr
posList :: [Integer] -> [Integer]
posList = filter (>0)
trueList :: [Bool] -> Bool
trueList = foldl' (&&) True
evenList :: [Integer] -> Bool
evenList x = foldl' (+) 2 x `mod` 2 == 0
-- `if True then True else False` is tautological
Run Code Online (Sandbox Code Playgroud)
所有这些签名都有效(包括改进的实现和原始的签名).
但他们只使用列表Integer.这并不总是足够笼统; 例如,计算分数列表的乘积是完全合理的.但是使用单形签名,mult [1.5, 2.4, 20]不起作用:这些数字不兼容Integer.您不希望将函数限制为整数,只是希望它可以使用任何数字类型,并始终获得与元素相同类型的结果.即,你基本上想要签名
mult :: ? a . [a] -> a
Run Code Online (Sandbox Code Playgroud)
...要读取"对于所有类型a,该函数mult采用一个列表,其元素具有类型a,并给出一个单a值作为结果.?当你有这样的类型变量时,隐含在Haskell中,即你可以做它
mult :: [a] -> a
Run Code Online (Sandbox Code Playgroud)
但这不起作用,因为该函数必须能够乘以元素.但这对所有类型都不可能,仅适用于数字类型.因此,您添加约束
mult :: Num a => [a] -> a
Run Code Online (Sandbox Code Playgroud)
因为posList它是一回事:签名本质上是
posList :: [a] -> [a]
Run Code Online (Sandbox Code Playgroud)
但是你还需要能够将(Ord)元素与0(Num)进行比较.因此约束
posList :: (Num a, Ord a) => [a] -> [a]
Run Code Online (Sandbox Code Playgroud)
在这种情况下evenList,数值运算是(+),(==)和mod.因此,在原则上,我们需要的Num,Eq和Integral,但Integral具有Num和Eq作为超无论如何,这样就足以:
evenList :: Integral a => [a] -> Bool
Run Code Online (Sandbox Code Playgroud)
......但是,这还不是最常见的形式.您可以使用折叠来减少该列表,但列表不是唯一可以折叠的内容,例如您也可以折叠数组,地图和Maybe值.可以折叠的所有容器的类型类都被调用,你不会猜到它Foldable.所以我们最终得到了
evenList :: (Integral a, Foldable t) => t a -> Bool
Run Code Online (Sandbox Code Playgroud)
您可以应用同样的泛化mult和trueList:
mult :: (Num a, Foldable t) => t a -> a
trueList :: Foldable t => t Bool -> Bool
Run Code Online (Sandbox Code Playgroud)