识别haskell类型

时间:2014-04-03 11:11:21

标签: haskell types functional-programming

我在理解haskell中的类型方面遇到了一些困难。让我们考虑以下函数并查看它们的类型。

reduce f s [] = s
reduce f s (x:xs) = f x (reduce f s xs)

for m n f s = if m>n then s else for (m+1) n f ( f m s )

comp f g x y = f x (g x y)

iter 0 f s = s
iter n f s = iter (n-1) f (f s)

我们有类似的东西:

reduce :: (t1 -> t -> t) -> t -> [t1] -> t
for :: (Ord a, Num a) => a -> a -> (a -> t -> t) -> t -> t
comp :: (t -> t2 -> t3) -> (t -> t1 -> t2) -> t -> t1 -> t3
iter :: (Num t) => t -> (t1 -> t1) -> t1 -> t1

我不清楚的是,在reduce函数中f取两个参数,而for f函数再取两个参数。我只能看到它只需要一个。好吧,如果它会是这样的:

for m n f s = if m>n then s else for (m+1) n f m n

更明显也很容易认识到f确实需要两个参数。

我想知道是否存在一些方法或方法来推断haskell中函数的类型。除了这些例子之外,我还要求提供一些不同的例子,这样我才能克服困难。

编辑:在我的情况下给出了函数定义,我只是想推断它们的类型

2 个答案:

答案 0 :(得分:6)

即使考虑f ( f m s ),你在思考错误的地方也是如此。那是 for定义的子表达式:回想一下,函数应用程序是从左边解析的。所以

for (m+1) n f ( f m s )
 ≡ (for (m+1)) n f ( f m s )
 ≡ (for (m+1) n) f ( f m s )
 ≡ (for (m+1) n f) ( f m s )
 ≇ (for (m+1) n ) (f ( f m s ))
 ≇ for (m+1) (n f ( f m s ))
 ≇ for ((m+1) n f ( f m s ))

最后的不平等可能是最明显的,因为你将函数(m+1)应用于三个参数......这看起来确实不太可能。

如果您需要任何"精神上的括号"为了理解函数,通常最好将它们放在每个函数参数周围:

for (m+1) n f ( f m s )
 ≡ for (m+1) 
       (n)
       (f)
       (f m s)

并且,如果这对您有所帮助,因为它看起来更像您在主流语言中的含义,那么您也可以取消所有内容:

 ≅ for ( m+1, n, f, f(m,s) )

(尽管你最好快点忘掉那个)


顺便说一句:如果你看到一个函数只应用于一个参数,那么它并不意味着函数类型只有 一个参数。事实上,Haskell的语法的主要优势在于你可以轻松地进行部分应用:例如。

  

前奏> :t取
  take :: Int - > [a] - >并[a]
  前奏> :t取3
  取3 :: [a] - >并[a]
  前奏>地图(拍3)[" looooong","甚至更长","非常长"]
  ["厕所""前夕""叔"]

您发现我只将take应用于一个参数,另一个参数会自map从列表中删除。

另一个例子,有操作符部分,

  

前奏> :t(+)
  (+):: Num a => a - > a - >一个
  前奏> :t(+ 1)
  (+ 1):: Num a => a - >一个
  前奏>地图(+ 1)[4,5,6]
  [5,6,7]

答案 1 :(得分:1)

以下定义中f的类型很容易推断

for m n f s = if m>n then s else for (m+1) n f ( f m s )

这可以改写为(清晰)

for m n f s 
    | m>n       = s
    | otherwise = for (m+1) n f ( f m s )
  1. for (m+1) n f (f m s)for

  2. 的来电
  3. 表示f m s需要与s具有相同的类型,

  4. 这需要f具有t1 -> t -> t类型 (t1mts