Haskell:函数组合的类型不匹配

时间:2016-06-22 15:40:20

标签: haskell types functional-programming function-composition combinators

我在功能构成和类型方面遇到了一些麻烦。 我想用filter撰写len(返回一个列表),它以列表作为参数(技术上是Foldable,但我在这里简化)。 看一下类型,一切都如预期:

> :t length
length :: Foldable t => t a -> Int

> :t filter
filter :: (a -> Bool) -> [a] -> [a]

所以现在我希望(len . filter)的类型是

(length . filter) :: (a -> Bool) -> [a] -> Int

虽然实际上是

> :t (length . filter)
(length . filter) :: Foldable ((->) [a]) => (a -> Bool) -> Int

所以我似乎失去了一些争论。是否以某种方式包含在Foldable要求中我不理解?

请注意,如果我执行部分应用程序,一切都按预期工作:

> let myFilter = filter odd
> :t myFilter
myFilter :: Integral a => [a] -> [a]
> :t (length . myFilter)
(length . myFilter) :: Integral a => [a] -> Int
>  (length . myFilter) [1,2,3]
2

3 个答案:

答案 0 :(得分:5)

正确的构成将是:

(length .) . filter :: (a -> Bool) -> [a] -> Int

相当于:

\pred xs -> length $ filter pred xs

如:

\> let count = (length .) . filter
\> :type count
count :: (a -> Bool) -> [a] -> Int
\> count odd [1..3]
2
\> count even [1..3]
1

答案 1 :(得分:4)

说明:

(.) :: (b -> c) -> (a -> b) -> a -> c
filter ::  (m -> Bool) -> [m] -> [m]
length :: Foldable t => t n -> Int

什么是u

length . filter :: u
≡ (.) length filter :: u

然后我们必须解决a, b, c, t, n

a -> b ~ (m -> Bool) -> [m] -> [m]
b -> c ~ Foldable t => t n -> Int

接下来:

a ~ m -> Bool
b ~ Foldable t => t n
b ~ [m] -> [m]
c ~ Int

中平凡:

a = m -> Bool
b = [m] -> [m]
c = Int

我们必须从t, n解决b ~ Foldable t => t n,即[m] -> [m] ~ Foldable t => t n

t = ((->) [m])
n = [m]

因此,t n = [m] -> [m]简单地统一。

汇总:

(.) :: Foldable ((->) [m]) =>
          (([m] -> [m]) -> Int)
       -> ((m -> Bool) -> [m] -> [m])
       -> (m -> Bool) -> Int

filter :: (m -> Bool) -> [m] -> [m]

length :: Foldable ((->) [m]) => ([m] -> [m]) -> Int

(.) length filter :: Foldable ((->) [m]) => (m -> Bool) -> Int

了解length . filter为什么不是您想要的更简单的方法是查看(.)的定义。

(.) g f x = g(f x)

因此:

(.) length filter
≡ \x -> length (filter x)

我们知道filter x不是列表。

您可以考虑的无意义版本:

(length .) . filter

filter >=> return . length

(fmap.fmap) length filter

(id ~> id ~> length) filter -- [1]

filter $* id $$ id *$ length -- [2]

lurryA @N2 (length <$> (filter <$> _1 <*> _2)) -- [3]
  1. Control.Compose
  2. Data.Function.Meld
  3. Data.Function.Tacit

答案 2 :(得分:2)

使用"three laws of operator sections",我们有

((length .) . filter) x y =
 (length .) (filter x) y =
 (length . filter x) y =
 length (filter x y)

((length .) . filter) = 
  (.) (length .) filter =
  (.) ((.) length) filter =
  ((.) . (.)) length filter

最后一位((.).(.))有时称为"owl operator",也称为.:length .: filter)或fmap . fmap(对于函数,{ {1}}是fmap)。