Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell中简单的依赖类型的温度转换器,是否可以缩短此代码?_Haskell_Dependent Type_Idris - Fatal编程技术网

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

Haskell中简单的依赖类型的温度转换器,是否可以缩短此代码?,haskell,dependent-type,idris,Haskell,Dependent Type,Idris,下面的函数convert具有类型签名: SUnit fromUnit->SUnit toUnit->Value fromUnit->Value toUnit 具有冗余,因为相同的信息可以通过以下方式表示: 单位值->单位值 1) 有没有办法去掉前两个参数(sunitfromUnit->sunittoUnit) 2) 有没有其他方法可以让这个简单的依赖类型的程序编写得更优雅 3) 这个程序在Idris中会是什么样子 {-# LANGUAGE GADTs,DataKinds,KindSignatur

下面的函数
convert
具有类型签名:

SUnit fromUnit->SUnit toUnit->Value fromUnit->Value toUnit

具有冗余,因为相同的信息可以通过以下方式表示:

单位值->单位值

1) 有没有办法去掉前两个参数(
sunitfromUnit->sunittoUnit

2) 有没有其他方法可以让这个简单的依赖类型的程序编写得更优雅

3) 这个程序在Idris中会是什么样子

{-# LANGUAGE GADTs,DataKinds,KindSignatures #-}
main=do
    putStrLn "Hello !"
--  putStrLn $ show $ convert SCelsius  SCelsius kelvinZero -- this line does not compile
    putStrLn $ show $ convert SKelvin SKelvin  kelvinZero -- prints Value 0.0
    putStrLn $ show $ convert SKelvin SCelsius kelvinZero -- prints Value (-273.16)

newtype Value (unit::Unit) = Value Double deriving Show
data Unit = Celsius | Kelvin

data SUnit u where
  SCelsius:: SUnit Celsius
  SKelvin::  SUnit Kelvin

offset=273.16
convert :: SUnit fromUnit-> SUnit toUnit ->Value fromUnit -> Value toUnit
convert          SCelsius         SKelvin  (Value tempCel) = Value $tempCel+offset
convert          SCelsius         SCelsius (Value tempCel) = Value $tempCel
convert          SKelvin          SCelsius (Value tempK)   = Value $tempK-offset
convert          SKelvin          SKelvin  (Value tempK)   = Value $tempK

kelvinZero::(Value 'Kelvin)
kelvinZero= Value 0

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

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.

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

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.

Ps,对于那些想知道如何在Idris中编写的人,Idris手册第3.4.3章“在函数中使用隐式参数”似乎是答案所在。Ps,对于那些想知道如何在Idris中编写的人,Idris手册第3.4.3章“在函数中使用隐式参数”似乎是答案所在。这很有用,因为它简化了调用方代码。这很有用,因为它简化了调用方代码。