module Tf0 where
all' :: (a -> Bool) -> [a] -> Bool
all' p = foldr (&&) True . map p
main :: IO()
xs = [1,3,5,7,9]
xs1 = [1,3,11,4,15]
k1 = all' (<10) xs
k2 = all' (<10) xs1
k3 = all' (<10)
main = print k1
问题:
在函数定义(all' p = foldr (&&) True . map p
)中没有列表作为输入,而函数Type显示列表作为输入([a]
),但试图检查函数(参见吼叫k1
,k2
,k3
)表明需要一个列表。
如何在没有列表的情况下定义函数?
答案 0 :(得分:4)
Haskell的一个基本方面是概念一个函数总是需要一个参数。确实采用了函数(+)
:
(+) :: Int -> Int -> Int
(技术上它是(+) :: Num a => a -> a -> a
,但让我们保持简单)。
现在你可以说(+)
有两个参数,但从概念上讲它需要一个参数。确实:签名实际上是
(+) :: Int -> (Int -> Int)
所以你喂它一个整数然后它返回一个函数,例如:
(+) 5 :: Int -> Int
所以你给它一个5
构造了一个函数,它将给一个给定的操作数加上5(同样是一个带一个参数的函数)。
现在将此问题应用于您的问题,all'
的签名实际上是:
all' :: (a -> Bool) -> ([a] -> Bool)
因此,如果您将all'
应用于一个参数,则会返回一个将列表[a]
映射到Bool
的函数。为了论证我们将p
设置为\_ -> True
,然后我们返回:
foldr (&&) True . map (\_ -> True) :: [a] -> Bool
确实是一个获取列表[a]
并将其映射到Bool
的函数。在下一阶段中,您将列表应用于 (返回)功能。
换句话说,函数式编程可以看作是一个长期的专业化函数链,直到它完全接地并且可以被评估。
Haskell只以优雅的方式提供它,这样您就不必考虑函数生成函数。但从概念上讲,这种情况一直都在发生。如果你想实现一个函数f :: a -> b -> c
,你可以这样做:
f x y = g (x+1) y
(使用g :: a -> b -> c
),但您也可以决定退出参数,并将其定义为:
f x = g (x+1)
因为g (x+1)
将返回最终可以应用y
的函数。