List Haskell中的长度函数和类型类

List Haskell中的长度函数和类型类,list,haskell,List,Haskell,这是一个工作函数,它遍历一个数字列表,并将每个元素与以下元素相加 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) 我

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

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)
我不明白我做错了什么,有人能告诉我吗?

函数总是返回一个
Int
,所以你试图用
(Num a)=>a
除以
Int
。该函数将
Int
转换为任何
Num
类型:

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
    功能只是前奏曲的
    sum
  • 我假设您并不总是想要一个
    整数
    平均值,因此我将
    media2
    上的约束更改为
    分数
    ,而不是
    Num
    。这是因为
    /
    的类型为
    (/)::(分数a)=>a->a->a
    。或者,您可以使用

    media2 :: (Fractional a) => [a] -> a
    media2 str = (media str) / (fromIntegral $ length str)
    
    但是你总是会得到一个积分平均值,这可能不是你想要的

  • 该函数始终返回一个
    Int
    ,因此您试图将
    (Num a)=>a
    除以
    Int
    。该函数将
    Int
    转换为任何
    Num
    类型:

    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
    功能只是前奏曲的
    sum
  • 我假设您并不总是想要一个
    整数
    平均值,因此我将
    media2
    上的约束更改为
    分数
    ,而不是
    Num
    。这是因为
    /
    的类型为
    (/)::(分数a)=>a->a->a
    。或者,您可以使用

    media2 :: (Fractional a) => [a] -> a
    media2 str = (media str) / (fromIntegral $ length str)
    
    但是你总是会得到一个积分平均值,这可能不是你想要的

  • 您可以使用from
    数据。列表

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

    它的类型签名是

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

    genericLength :: Num i => [a] -> i 
    
    您可以使用from
    数据。列表

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

    它的类型签名是

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

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

    它说,
    media str
    有type
    a
    length str
    有type
    Int
    ,你不能用一个除以另一个,因为它不能证明
    a
    实际上是
    Int
    ;它叫
    sum
    。它说
    media str
    有type
    a
    length str
    有type
    Int
    ,你不能用一个除以另一个,因为它不能证明
    a
    实际上是
    Int
    。Haskell已经有了一个函数来做
    media
    所做的事情;它被称为
    sum
    。对于来自其他语言的人来说,非直观的一点是
    /
    Haskell
    中处理
    Int
    时不会过载。您必须显式使用整数除法(使用
    quot
    div
    ),或将分子和分母转换为实现
    分数的东西。
    media2
    的类型应为
    分数a=>[a]->a
    Num a
    不足。对于来自其他语言的人来说,非直观的一点是
    /
    Haskell
    中处理
    Int
    s时不会过载。您必须显式使用整数除法(使用
    quot
    div
    ),或将分子和分母转换为实现
    分数的东西。
    media2
    的类型应为
    分数a=>[a]->a
    <代码>数值a
    不足。