【问题标题】:Length function and type classes in Haskell [duplicate]Haskell中的长度函数和类型类[重复]
【发布时间】:2014-07-22 02:57:07
【问题描述】:
media :: (Num a) => [a] -> a
media [] = 0
media lst = (head lst) + media (tail lst)

这是一个工作函数,它遍历一个数字列表并将每个元素与以下元素相加。

media2 :: (Num a) => [a] -> a
media2 str = (media str) / (length str)

第二个函数应该得到该总和并将其除以列表的长度,从而获得列表的算术平均值。但是编译器返回给我这个

src/Main.hs@6:29-6:39Could not deduce (a ~ Int)
from the context (Num a)
bound by the type signature for media2 :: Num a => [a] -> a
at /home/app/isolation-runner-work/projects/32614/src.207/Main.hs:6:1-39
`a' is a rigid type variable bound by
the type signature for media2 :: Num a => [a] -> a
at /home/app/isolation-runner-work/projects/32614/src.207/Main.hs:6:1
In the return type of a call of `length'
In the second argument of `(/)', namely `(length str)'
In the expression: (media str) / (length str)

我不明白我做错了什么,有人可以告诉我吗?

【问题讨论】:

  • 它说media str 的类型为alength str 的类型为Int,您不能将其一分为二,因为它不能证明a 实际上是Int .
  • Haskell 已经有一个函数可以做media 所做的事情;它被称为sum

标签: list haskell


【解决方案1】:

length 函数始终返回 Int,因此您试图将 (Num a) => a 除以 IntfromIntegral 函数会将Int 转换为任何Num 类型:

media2 :: (Fractional a) => [a] -> a
media2 str = (media str) / (fromIntegral $ length str)

编辑

简单介绍一些有见地的 cmets:

  1. 您的 media 函数只是 Prelude 的 sum
  2. 我假设您并不总是想要 Integral 平均值,因此我将 media2 的约束更改为 Fractional 而不是 Num。这是因为/ 的类型为(/) :: (Fractional a) => a -> a -> a。或者,您可以使用

    media2 :: (Integral a) => [a] -> a
    media2 str = (media str) `div` (fromIntegral $ length str)
    

    但你总是会得到一个积分平均值,这可能不是你想要的。

【讨论】:

  • 对于来自其他语言的人来说,不直观的一点是,/ 没有超载以在 Haskell 中处理 Ints。您要么必须显式使用整数除法(使用quotdiv),要么将分子和分母转换为实现Fractional 的东西。
  • media2 的类型应为 Fractional a => [a] -> aNum a 不够用。
【解决方案2】:

您可以从Data.List 使用genericLength

genericLength 函数是长度的重载版本。特别是,它不是返回 Int,而是返回作为 Num 实例的任何类型。但是,它的效率低于长度。

它的类型签名是

genericLength :: Num i => [a] -> i 

用法:

import Data.List

media2 :: (Num a) => [a] -> a
media2 str = (media str) / (genericLength str)

【讨论】:

    猜你喜欢
    • 2020-07-11
    • 2015-12-17
    • 2014-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-31
    • 1970-01-01
    相关资源
    最近更新 更多