你可以说“20::Double”的原因是,在 Haskell 中,整数文字的类型为“Num a => a”,这意味着它可以是你喜欢的任何数字类型。
你是对的,类型类是一组类型。准确地说,它是实现类型类的“where”子句中的功能的类型集。您的 numToDouble 类型签名正确表达了您想要执行的操作。
您对函数中“n”类型的值所了解的只是它实现了 Num 接口。它由 +、-、*、negate、abs、signum 和 fromInteger 组成。最后一个是唯一进行类型转换的,但它对您想要的没有任何用处。
请记住,Complex 也是 Num 的一个实例。 numToDouble 应该做什么呢?正确的事情并不明显,这也是你遇到问题的部分原因。
然而,在类型层次结构的下方,您拥有 Real 类型类,它具有您可能想要使用的所有更简单的数字类型的实例,例如浮点数、双精度数和各种类型的整数。其中包括一个函数“toRational”,它将任何实际值转换为比率,您可以使用“fromRational”将其转换为 Double,它是“Fractional”类型类的函数。
So try:
toDouble :: (Real n) => n -> Double
toDouble = fromRational . toRational
但当然这实际上太具体了。 GHCI 说:
Prelude> :type fromRational . toRational
fromRational . toRational :: (Fractional c, Real a) => a -> c
因此它将任何实数类型转换为任何分数类型(后者涵盖了任何可以进行除法的东西,包括不是实数实例的东西,例如复数)当搞乱数字类型时,我不断发现自己将它用作一种通用数字强迫。
Edit:正如 leftaroundabout 所说,
realToFrac = fromRational . toRational