在Haskell中简单依赖类型的温度转换器,是否可以缩短此代码?

时间:2016-01-03 10:11:47

标签: haskell dependent-type idris

下面的函数convert具有类型签名: 来自Unit->的SUnit SUNit toUnit - > Value fromUnit - >值得单位, 它具有冗余,因为相同的信息可以表示为: 来自单位的价值 - >价值toUnit。 1)有没有办法摆脱前两个参数(SUnit fromUnit-> SUnit toUnit)? 2)是否有其他方式可以更优雅地编写这个简单依赖类型的程序? 3)这个程序在伊德里斯看起来怎么样? { - #LANGUAGE GADTs,DataKinds,KindSignatures# - } 主要=做     putStrLn"你好!" - putStrLn $ show $ convert SCelsius SCelsius kelvinZero - 此行无法编译     putStrLn $ show $ convert SKelvin SKelvin kelvinZero - 打印价值0.0     putStrLn $ show $ convert SKelvin SCelsius kelvinZero - 版画值(-273.16) newtype Value(unit :: Unit)= Value Double derived Show 数据单位=摄氏度|开 数据SUnit u在哪里   SCelsius :: SUnit Celsius   SKelvin :: SUnit Kelvin 偏移量= 273.16 convert :: SUnit fromUnit-> SUNit toUnit - > Value fromUnit - >价值toUnit 转换SCelsius SKelvin(值tempCel)=值$ tempCel + offset 转换SCelsius SCelsius(值tempCel)=值$ tempCel 转换SKelvin SCelsius(值tempK)=值$ tempK-offset 转换SKelvin SKelvin(价值tempK)=价值$ tempK kelvinZero ::(Value' Kelvin) kelvinZero =价值0

1 个答案:

答案 0 :(得分:4)

如果要删除前两个参数,在Haskell中需要一个类型类。

class IsUnit a where
   getSUnit :: SUnit a
instance IsUnit Celsius where getSUnit = SCelsius
instance IsUnit Kelvin  where getSUnit = SKelvin

convertShort :: (IsUnit fromUnit, IsUnit toUnit) => Value fromUnit -> Value toUnit
convertShort = convert getSUnit getSUnit

请注意,这会使代码更长,而不是更短 - 但它允许调用者省略第一个单例值。

上述代码还假设每个单元都可以转换为任何其他单元,这是不现实的。原始代码也包含此问题。如果不需要,可以使用双参数类型:

class C from to where convert :: Value from -> Value to
instance C Kelvin Celsius where ...
-- etc.