gpt4 book ai didi

Haskell 的类型关联链令人费解

转载 作者:行者123 更新时间:2023-12-02 05:25:01 24 4
gpt4 key购买 nike

我正在玩一些 Haskell 代码。我定义了两个函数:

count :: [a] -> Int
count [] = 0
count (x:xs) = 1 + (count xs)

-- 03. Write a function that computes the mean of a list, i.e., the sum of all
-- elements in the list divided by its length. (You may need to use the
-- fromIntegralfunction to convert the length of the list from an integer
-- into a floating-point number.)

-- I've guessed this type definition, but it's incorrect:
-- listMean :: [a] -> Double
-- The following is the same inferred by hgci
listMean :: (Fractional a) => [a] -> a
listMean lst = (foldl1 (+) lst)/(fromIntegral (count lst))

为什么 [a] -> Double 不正确?似乎我给出的 lst 是某种类型 a 的通用列表,而 listMean 返回一个 Double。我做错了什么?

谢谢,阿尔弗雷多

最佳答案

首先,listMean::[a] -> Double 表示 listMean 是一个接受任意类型 a 列表的函数到单个 Double 值。

但是您依赖于能够将 (+) 应用于列表 (foldl1 (+)) 的元素,这需要类型 a Num 的实例,这意味着您至少有:

listMean :: (Num a) => [a] -> b

您还将 (/) 应用于 foldl1 操作产生的类型 a 的值。为此,a 必须不仅是 Num 的实例,而且是 Fractional 的实例。将此要求应用于类型 a 给出类型签名:

listMean :: (Fractional a) => [a] -> b

现在,b 呢?那么,(/) 的签名是 (/)::(Fractional a) => a -> a -> a。因此,listMean 的结果也必须是 Fractional 的实例。此外,它必须与列表中包含的 Fractional 的实例相同:类型 b 因此实际上是类型 a,并且listMean 最通用的签名是:

listMean :: (Fractional a) => [a] -> a

这正是编译器推断的。如果你想专门针对 Double,你必须用 Double 替换 both 出现的 a:

listMean :: [Double] -> Double

这是因为你没有运算符将 Fractional 的任何实例强制转换为 Double,所以输入和输出都到 (/) 必须是 Double 类型。

关于Haskell 的类型关联链令人费解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4081053/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com