haskell - 函数签名如何匹配请求的类型

标签 haskell type-inference

我试图了解这是如何工作的;在 GHCi 中:

foldMap (+3) (Just 5) :: Sum Int

产生结果
Sum {getSum = 8}

现在, foldMap 的类型是
foldMap :: (Foldable t, Monoid m) => (a -> m) -> t a -> m

并且从 foldMap 使用的函数的类型签名与使用函数的签名(+3)不匹配:
(+3) :: Num a => a -> a

对比
f :: Monoid m => a -> m

如果我也尝试这样的事情:
foldMap _ (Just 5) :: Sum Int
---------------------------------------
<interactive>:113:9: error:  
* Found hole: _ :: Integer -> Sum Int  
* In the first argument of `foldMap', namely `_'  
  In the expression: foldMap _ (Just 5) :: Sum Int  
....

这也表明预期函数具有签名 :: (Integer -> Sum Int)哪个与 foldMap 声明中的签名一致但与上面使用的 (+3) 不一致?我对 foldMap 的理解是它应用函数将 Foldable 实例的每个元素转换为 Monoid 然后可以折叠成单个值。

我假设编译器推断应该是什么类型(在上面的行中明确说明)但我不明白的是编译器如何“调整”函数(+3)的类型签名以便第一行编译?

最佳答案

总之 : 自 instance Num a => Num (Sum a)持有,您的 5被视为 Sum Int .

给定 aNum类型, Sum a , 是 Num类型。确实,在documentation我们看:

Num a => Num (Sum a)


现在是 Num类型 n有一个功能fromInteger :: Integer -> n转换 Integer进入那个数字类型 n .这个想法是,如果你这样写 5 , 你隐含地写了类似 fromInteger 5 的东西.

通过写作
foldMap (+3) (Just 5) :: Sum Int

foldMap :: (Foldable f, Monoid m) => (a -> m) -> t a -> m 因此我们知道 m应该是 Sum Int ,那 t ~ Maybe ,以及自 (+3) :: Num a => a -> a , 表示 m ~ a ~ Sum Int .因此,这意味着 5 (来自 Just 5)和 3 (来自 (+3))是 Sum Int s。 5您写的内容因此被解释为 Sum 5 .这同样适用于 3 .

所以现在我们知道我们实际上已经写了:
foldMap (+ (Sum 3)) (Just (Sum 5)) :: Sum Int
foldMap将结构的每个元素映射到一个幺半群(它已经是一个幺半群,但无论如何它会用 3 递增它们),然后执行折叠。所以这意味着我们已经写了这样的东西:
(+ (Sum 3)) (Sum 5) <> mempty

对于 Num n => Sum n输入 memptySum 0 ,所以这意味着我们写道:
(+ (Sum 3)) (Sum 5) <> (Sum 0)

(<>)对于 Sum(+) ,所以这意味着表达式归结为:
(+ (Sum 3)) (Sum 5) + (Sum 0)

可以评估为:
(Sum 5 + Sum 3) + Sum 0

或者:
Sum 8

关于haskell - 函数签名如何匹配请求的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51746869/

相关文章:

c# - C# 中的泛型类型推断

java - Scala:使用类型参数信息访问静态 Java 方法

typescript - 不要扩大对象字面量中潜在的字面量类型

haskell - 如何在 IHP 中处理日期?有没有 'default'的方法?

haskell - 用 Parsec 解析 Haskell 的子集

haskell - 是什么导致这种类型的歧义?

typescript 构造函数泛型参数推断

typescript - 对象字面量出现“不可分配给类型参数”错误

testing - 如何在 SmallCheck 中使用 monadic 属性?

haskell - 我应该使用 monad 还是 EfforT monad 转换器?