Существует ли эквивалент Haskell единиц измерения F #?
F # имеет единицы измерения, описанные в http://msdn.microsoft.com/en-us/library/dd233243.aspx следующим образом:
[<Measure>] type unit-name [ = measure ]
Это позволяет определять единицы измерения, такие как:
type [<Measure>] USD
type [<Measure>] EUR
И код, который будет записан как:
let dollars = 25.0<USD>
let euros = 25.0<EUR>
// Results in an error as the units differ
if dollars > euros then printfn "Greater!"
Он также обрабатывает конверсии (я предполагаю, что означает, что "Мера" имеет определенные функции, которые позволяют умножать, делить и экспонировать Меры):
// Mass, grams.
[<Measure>] type g
// Mass, kilograms.
[<Measure>] type kg
let gramsPerKilogram: float<g kg^-1> = 1000.0<g/kg>
let convertGramsToKilograms (x: float<g>) = x / gramsPerKilogram
Мои инстинкты говорят мне, что в Haskell возможно реализовать аналогичную возможность, но я не смог найти примеров того, как это сделать.
Изменить: о, мое слово, это огромная баня червей! Там есть исследовательский документ http://research.microsoft.com/en-us/um/people/akenn/units/CEFP09TypesForUnitsOfMeasure.pdf. Я предполагаю, что это более чем несколько строк кода для реализации всего. Летний проект?:)
Ответы
Ответ 1
Заверните числа в newtype и дайте им экземпляр Num
.
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype GBP n = GBP n deriving (Show, Num, Eq, Ord)
newtype USD n = USD n deriving (Show, Num, Eq, Ord)
Использование:
ghci> let a1 = GBP 2
ghci> let a2 = GBP 5
ghci> a1 + a2
GBP 7
ghci> let b1 = USD 3
ghci> let b2 = USD 6
ghci> b1 + b2
USD 9
ghci> a1 + b2 -- should be an error for mixing currencies
<interactive>:8:6:
Couldn't match expected type `GBP Integer'
with actual type `USD Integer'
In the second argument of `(+)', namely `b2'
In the expression: a1 + b2
In an equation for `it': it = a1 + b2
Ответ 2
dimensional и dimensional-tf ( с типами семейств вместо классов с несколькими параметрами) библиотеки довольно приятны и могут обрабатывать большинство проблем, представленных в вашем примере.
Я не думаю, что библиотека позволяет вам определять настраиваемые параметры, такие как валюты. Насколько я знаю, вам нужно будет изменить код библиотеки, чтобы сделать это.
Ответ 3
OK. Я знаю, что вопрос слишком стар. Но есть сборка плагина GHC для обеспечения возможности единицы измерения в Haskell. Пожалуйста, обратитесь к этому документу Adam Gundry .
Ответ 4
Пакет units кажется многообещающим и позволяет конвертировать между различными единицами того же размера. Тем не менее, я не использовал его, и я не знаю, стабилен он или нет. Справедливости ради, я попытался установить его сегодня, и установка завершилась неудачно...
Ответ 5
Проверьте haskell.org wikipage о том, как принудительно использовать блоки в Haskell:
https://wiki.haskell.org/Physical_units
Существует несколько вариантов, но я не уверен, действительно ли что-то похожее на "Единицы измерения", которые вы упомянули.
Ответ 6
Я не знаю Haskell, хотя я заинтересован в обучении и все еще младше с F #, однако, кажется, общее решение должно быть связано с обработкой мер как кортежа скаляра и метки, представляющей единицу, (N, М).
Например, пусть мера является общим набором из measure<N,M>
, где N
является числом, а M
является string
, тогда =, +, -, *, /, ^
может быть перегружен для реализации оценки для данных мер, a, b, and c
, скаляр p
, boolean k и нормировочная функция метки метки norm
такая, что
a = b = (Na,Ma) = (Nb,Mb) = (Na = Nb) and norm(Ma) = norm(Mb) = k
a + b = (Na,Ma) + (Nb,Mb) = (Na + Nb, Ma) = c provided norm(Ma) = norm(Mb)
a * b = (Na,Ma) * (Nb,Mb) = (Na * Nb, Ma * Mb) = c
a ^ p = (Na,Ma) ^ p = (Na ^ p , Ma ^ p ) = c
....