我是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
所以,我知道你可以通过不同的方式更容易地完成这些功能,但我有使用更高阶函数map
,filter
和foldr
的任务,所以我必须这样做他们那样。无论如何,我理解函数是如何工作的,因为我是编写它们的人,我不理解的是那些术语Integral
,Foldable
,它们是什么意思?他们用Haskell称之为什么?
答案 0 :(得分:5)
这些是对多态类型的约束。
Haskell尽管是静态类型的,但通过名为parametric polymorphism的系统,可以很容易地编写可以使用不同类型的函数。我将首先为您的所有功能提供具体(单态)签名:
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
所有这些签名都有效(包括改进的实施和原始的签名)。
但他们仅使用Integer
列表。这并不总是足够普遍;例如,计算分数列表的乘积是完全合理的。但是使用单态签名时,mult [1.5, 2.4, 20]
不起作用:这些数字与Integer
不兼容。您不希望将函数限制为整数,您只希望它可以使用任何数字类型,并始终获得与元素相同类型的结果。即,你基本上想要签名
mult :: ∀ a . [a] -> a
...要阅读"对于所有类型a
,函数mult
采用其元素类型为a
的列表,并提供单个a
结果是-value。当你有这样的类型变量时,∀
隐含在Haskell中,即你可以做到它
mult :: [a] -> a
然而,这还不起作用,因为该函数必须能够乘以元素。但对于所有类型,这是不可能的,仅适用于number types。因此,您添加约束
mult :: Num a => [a] -> a
对于posList
来说,情况大致相同:签名本质上是
posList :: [a] -> [a]
但您还需要能够将元素与Ord
(0
)进行比较(Num
)。因此约束
posList :: (Num a, Ord a) => [a] -> [a]
如果是evenList
,则数字操作为(+)
,(==)
和mod
。因此原则上我们需要Num
,Eq
和Integral
,但Integral
有Num
和Eq
为超类无论如何,仅此一点就足够了:
evenList :: Integral a => [a] -> Bool
......但这还不是最常见的形式。您可以使用折叠来减少该列表,但列表不是唯一可以折叠的内容,例如您还可以折叠数组,地图和Maybe
值。可以折叠的所有容器的类型类都被调用,你不会猜它,Foldable
。所以我们最终得到了
evenList :: (Integral a, Foldable t) => t a -> Bool
您可以将相同的推广应用于mult
和trueList
:
mult :: (Num a, Foldable t) => t a -> a
trueList :: Foldable t => t Bool -> Bool