gpt4 book ai didi

haskell - 应用于 Haskell 中标记类型的通用函数

转载 作者:行者123 更新时间:2023-12-02 06:34:30 32 4
gpt4 key购买 nike

假设我已经定义了这些类型:

data Km     = Km Float deriving (Show, Eq)
data Mile = Mile Float deriving (Show, Eq)
data Meter = Meter Float deriving (Show, Eq)
data Feet = Feet Float deriving (Show, Eq)

我有一些功能,例如:

kms_to_miles    :: Km   -> Meter
kms_to_feets :: Km -> Feet
miles_to_meters :: Mile -> Meter

这太完美了,因为我不能混用单位。

现在,如果我有一些简单的功能:

doubleTheDistance' :: Float -> Float
doubleTheDistance' x = 2 * x

我想将它应用到我可以的类型中:

class Dbl a where
doubleTheDistance :: a -> a
instance Dbl Km where
doubleTheDistance (Km x) = Km (2 * x)
instance Dbl Mile where
doubleTheDistance (Mile x) = Mile (2 * x)
-- an instance with the same for all my types here...

因为我的类型不是参数化的,所以我不能使用 Functor 并在它们上面映射一个通用函数 (doubleTheDistance')。

我错过了什么吗?有什么方法可以抽象这种行为,这样我就不必为每个标记类型编写相同的函数了吗?

最佳答案

另一种方法是使用 phantom type编码“单位”。它仍然为您提供类型安全的特定类型,例如 Distance Km,但也允许您在需要时应用更通用的函数,例如 doubleTheDistance:

data Km
data Mile
data Meter
data Feet

data Distance m = Distance Float deriving (Show, Eq)

kms_to_miles :: Distance Km -> Distance Mile
kms_to_miles (Distance km) = Distance (km*0.621371192)

doubleTheDistance :: Distance m -> Distance m
doubleTheDistance (Distance x) = Distance (2 * x)

-- Tests
km = Distance 5 :: Distance Km

doubled = doubleTheDistance km

您甚至可以显示您的距离:

{-# LANGUAGE ScopedTypeVariables  #-}

data Km
data Mile
data Meter
data Feet

data Distance m = Distance Float deriving Eq

instance Show Km where
show _ = "km"
instance Show Mile where
show _ = "ml"
instance Show Feet where
show _ = "ft"

instance Show m => Show (Distance m) where
show (Distance a) = show a ++ " " ++ show (undefined :: m)

km = Distance 5 :: Distance Km -- Is shown as "0.5 km"

关于haskell - 应用于 Haskell 中标记类型的通用函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23244526/

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