Функция convert
ниже имеет тип подписи:Простой в использовании температурный преобразователь в Haskell, возможно ли сократить этот код?
SUnit fromUnit-> SUnit toUnit ->Value fromUnit -> Value toUnit
,
который имеет избыточность, так как та же информация может быть выражена:
Value fromUnit -> Value toUnit
.
1) Есть ли способ избавиться от первых двух аргументов (SUnit fromUnit-> SUnit toUnit
)?
2) Есть ли другой способ, с помощью которого эта простая навязчивая программа может быть написана более элегантно?
3) Как эта программа будет выглядеть в Идрисе?
{-# 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
Ps, для тех, кто задается вопросом, как это может быть написано в Идриса книге Идриса, глава «3.4.3 Использование неявных аргументов в функции «Кажется, где ответ. – jhegedus