【问题标题】:Why doesn't this haskell type signature work?为什么这个 haskell 类型签名不起作用?
【发布时间】:2015-05-25 19:46:21
【问题描述】:

haskell 的新人在这里。我正在尝试更好地编写类型签名,而这个简单的签名并不想工作。我想知道为什么:

average :: Num a => [a] -> a
average ns = sum ns `div` length ns

Average 应该取任意数字并返回某个数字。但是我得到了错误

test.hs 11:27:
    Couldn't match expected type 'a' with actual type 'Int'
       'a' is a rigid type variable bound by
       the type signature for average :: Num a => [a] -> a
        at test.hs:10:12
    Relevant bindings include
        ns:: [a] (bound at test.hs:11:9)
        average :: [a] -> a (bound at test.hs:11:1)
    In the second argument of 'div' namely 'length ns'
    In the expression: sum ns `div ` length ns

这似乎是在说长度没有达到它的预期。任何人都可以帮忙吗?

【问题讨论】:

  • 这是因为 length nsIntdiv 适用于 Integral a => a -> a -> a - 试试 average ns = sum ns div` (fromIntegral $ length ns)` - 它应该可以工作
  • 但在小事上:div 无论如何都需要Integral
  • length :: [q] -> Int 所以average :: [Int] -> Int.

标签: haskell types type-signature


【解决方案1】:

好的,这会起作用:

average :: Integral a => [a] -> a
average ns = sum ns `div` (fromIntegral $ length ns)

请注意div :: Integral a => a -> a -> a,因此您需要Integral a 而不仅仅是Num a(没有除法)

因为length 将返回Int,所以您需要fromIntegral 来解决它。

【讨论】:

  • 嗯,我什至没有想过使用 :type 来弄清楚 div 是什么。感谢您的帮助
  • np - 数字和它们的关系/转换也总是让我着迷 - 真正的乐趣始于浮动、罪恶等;)
【解决方案2】:

div 的类型是Integral a => a -> a -> a,这意味着它的两个参数必须是相同的类型。在这种情况下,第二个参数始终是 Int 类型(length 的结果),但第一个参数是 a 类型。

此外,您正在尝试编写一个适用于任何类型的Num 的函数,但div 仅适用于整数类型。如果你想支持整数值的“平均”列表(结果也被四舍五入为整数),你可以这样做:

average :: Integral a => [a] -> a
average ns = sum ns `div` fromIntegral (length ns)

fromIntegral 会将Int 长度转换为a 的任何整数类型(可能是Int,或类似Integer)。

为避免舍入错误,您需要对小数类型使用小数除法:

average :: Fractional a => [a] -> a
average ns = sum ns / fromIntegral (length ns)

【讨论】:

  • 好点 - 我确实忘记了 div 可能不是最好的主意 ;)
【解决方案3】:

其他答案很好地突出了NumIntegral 的问题,在调用length 后提供使用演员表。或者,您可以使用来自Data.ListgenericLength

import Data.List

average :: Integral a => [a] -> a
average ns = sum ns `div` genericLength ns

【讨论】:

    猜你喜欢
    • 2010-10-27
    • 1970-01-01
    • 1970-01-01
    • 2023-01-21
    • 2016-01-26
    • 1970-01-01
    • 2013-12-25
    • 1970-01-01
    • 2012-02-13
    相关资源
    最近更新 更多