繁体   English   中英

带有函数组合的类型推断列表

[英]Type inference list with function composition

我试图使用折叠来取得Haskell中整数之和的平方。 但是,我从GHCi那里得到了一个神秘的错误。 这是我的单行:

((^2) . foldl) (+) 0 [1..100]

我从GHCi得到的是:

Prelude> ((^2) . foldl) (+) 0 [1..100]

<interactive>:19:3:
    No instance for (Num (b0 -> [b0] -> b0))
      arising from a use of `^'
    Possible fix:
      add an instance declaration for (Num (b0 -> [b0] -> b0))
    In the first argument of `(.)', namely `(^ 2)'
    In the expression: (^ 2) . foldl
    In the expression: ((^ 2) . foldl) (+) 0 [1 .. 100]

我认为问题出在我最后根据此类型声明传入的列表中。

Prelude> :t ((^2) . foldl) (+) 0 [1..100]
((^2) . foldl) (+) 0 [1..100]
  :: (Enum b, Num b, Num (b -> [b] -> b)) => b

任何人都可以让我深入了解为什么这种类型期望一个Enum和任何方式显式地转换列表,以便我可以调试此功能? 提前致谢。

是的,这仍然是GHC产生的最荒谬和无用的错误信息之一。

首先,忽略该消息,考虑foldl的类型和(.)

foldl :: (a -> b -> a) -> a -> [b] -> a
(.) :: (b -> c) -> (a -> b) -> a -> c

请注意, (.)只使用第一个参数组成。 由于currying,具有“多个”参数的函数实际上是一个返回另一个函数的参数的函数。 因此,在表达式((^2) . foldl)的“返回类型” foldla -> [b] -> a ,这是它试图与组成(^ 2)

并且因为错误消息是愚蠢的,它抱怨没有Num实例a -> [b] -> a以便用(^2) :: Num a => a -> a组成它并建议你添加一个。

你想要的是这样的: ((^2) . foldl (+) 0) 也就是说,使用(懒惰) foldl可能是一个坏主意。 最好使用严格的foldl'或者更好的是内置的sum函数: (^2) . sum (^2) . sum

此外,类型中提到的Enum约束是无关紧要的,事实上是正确的 - Enum类型类提供了用于解释范围表示法的函数。 所以(Enum b, Num b) => ...意味着b是一个可以枚举的数字类型,这正是表达式[1 .. 100]

写这个的正确方法是(^2) . foldl (+) 0 :: Num a => [a] -> a (^2) . foldl (+) 0 :: Num a => [a] -> a(^2) . foldl (+) 0 $ [1..100] :: (Num a, Enum a) => a (^2) . foldl (+) 0 $ [1..100] :: (Num a, Enum a) => a 当你这样做(^2) . foldl (^2) . foldl本身你试图设置第一个返回类型foldl的参数,它是一个函数a -> [a] -> a 该错误声明了这一点:它没有这种函数的Num实例,因此无法调度适当的幂函数(^)

通常,将组合(.)视为仅适用于单个输入函数的东西。 类型表明了这一点

(.) :: (b -> c) -> (a -> b) -> a -> c

虽然它有更多的一般用途,但它们有点难以找到。

所以我的解决方案有效,因为我在编写之前直接将参数应用于foldl 这些参数使foldl (+) 0 :: Num a => [a] -> a a单个输入参数的函数。

已经给出了很好的答案,但是编写它可能更直接

(^2) $ foldl (+) 0 [1..100]

表达式foldl (+) 0 [1..100]本身就可以工作,如果你试图理解foldl的工作原理,那么结果会传递给(^2) 写成一个函数

f list = (^2) $ foldl (+) 0 list

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM