gpt4 book ai didi

Haskell 返回类型多态性

转载 作者:行者123 更新时间:2023-12-02 22:37:15 25 4
gpt4 key购买 nike

我有以下数据结构:

data TempUnit = Kelvin Float
| Celcius Float
| Fahrenheit Float

我想实现一个将温度从开尔文转换为另一个单位的函数。如何将返回类型单元传递给函数?

最佳答案

一种方法是为不同的温度单位使用 3 种不同的类型,然后使用类型类将它们“联合”为温度,例如

newtype Kelvin = Kelvin Float
newtype Celcius = Celcius Float
newtype Fahrenheit = Fahrenheit Float

class TempUnit a where
fromKelvin :: Kelvin -> a
toKelvin :: a -> Kelvin

instance TempUnit Kelvin where
fromKelvin = id
toKelvin = id

instance TempUnit Celcius where
fromKelvin (Kelvin k) = Celcius (k - 273.15)
toKelvin (Celcius c) = Kelvin (c + 273.15)

instance TempUnit Fahrenheit where
fromKelvin (Kelvin k) = Fahrenheit ((k-273.15)*1.8 + 32)
toKelvin (Fahrenheit f) = Kelvin ((f - 32)/1.8 + 273.15

现在您可以使用 toKelvin/fromKelvin并且将根据(推断的)返回类型选择适当的实现,例如

absoluteZeroInF :: Fahrenheit 
absoluteZeroInF = fromKelvin (Kelvin 0)

(请注意使用 newtype 而不是 data ,这与 data 相同,但没有额外构造函数的运行时成本。)

该方法提供任意转换函数convert :: (TempUnit a, TempUnit b) => a -> b自动:convert = fromKelvin . toKelvin 。在这一点上,这需要编写处理任意温度的函数的类型签名 TempUnit a => ... a约束而不仅仅是简单的 TempUnit .

<小时/>

还可以使用“哨兵”值,否则该值将被忽略,例如

fromKelvin :: TempUnit -> TempUnit -> TempUnit
fromKelvin (Kelvin _) (Kelvin k) = Kelvin k
fromKelvin (Celcius _) (Kelvin k) = Celcius (k - 273.15)
fromKelvin (Fahrenheit _) (Kelvin k) = Fahrenheit (...)

(这可能通过 @seliopou 建议的方法更好地完成:分解一个单独的 Unit 类型。)

可以像这样使用:

-- aliases for convenience
toC = Celcius 0
toK = Kelvin 0
toF = Fahrenheit 0

fromKelvin toC (Kelvin 10)
fromKelvin toF (Kelvin 10000)

请注意,此方法不是类型安全:尝试转换 Celcius 100 时会发生什么与 fromKelvin ? (即 fromKelvin toF (Celcius 100) 的值是多少?)

<小时/>综上所述,最好在一个单位上进行内部标准化,并且仅在输入和输出上转换为其他单位,即只有读取或写入温度的函数需要担心转换,其他一切都可以使用(例如) Kelvin .

关于Haskell 返回类型多态性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14103927/

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