2013-06-11 10 views
15

F#が次のようにhttp://msdn.microsoft.com/en-us/library/dd233243.aspxで説明し、測定能力の単位を有する:F#単位のハスケル相当物はありますか?

[<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!" 

また、コンバージョンも処理されます(これは、Measureにはいくつかの機能があります対策は)、掛け分けて指数化させ、その罰金:

// 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です。私はそれがすべてのものを実装するコードの数行以上のものだと思っています。夏のプロジェクトの誰ですか? :)

+0

ことを正規化機能norm。長さ、質量などについても同じことができます。 – DiegoNolan

+4

[dimension](http://hackage.haskell.org/package/dimensional)をご覧ください。 Hackageのマニュアルは存在しませんが、[wiki上で]いくつかの例があります(https://code.google.com/p/dimensional/w/list?q=label:Example)。 – hammar

+2

'dimension'は実際の物理的なユニットのための良い提案ですが、お金のためのものではありません。 – leftaroundabout

答えて

12

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 
+9

私はHaskellについてよく分かりませんが、F#ユニットの能力の1つは、それらが乗算をサポートしていることです。例えば、 '1 /1 = 1 'です。つまり、タイプチェックのサポートを得ることができます物理方程式のあなたのHaskellはこれを実装していますか? –

+1

@JohnPalmer私が書いたように、それはうまくいかないでしょう。これを達成するには、少し複雑なシステムが必要です。左辺に記載されている[dimension](http://hackage.haskell.org/package/dimensional)パッケージには、そのようなことが含まれていますが、私はそれをまだ使用していないため、どれほど一般的ではありません。 –

+2

@JohnPalmerあなたの例では、JavaとC#で管理できる他のものと同様に、あるタイプの誤った扱いを防ぐことができます!私はF#の例の完全な機能をHaskellで達成することが可能かどうかを知りたいと思います(あるいは、何らかの方法でだまして、それを言語に埋め込んでいるかどうかを確かめてください)。 – Darren

7

dimensionaldimensional-tf(代わりに、マルチパラメータ型クラスの型家族との)ライブラリはかなりいいですし、あなたの例で提示問題のほとんどを処理することができます。

ライブラリでは、通貨などのカスタムディメンションを定義することはできません。私が知る限り、ライブラリコードを変更する必要があります。

1

unitsパッケージは有望であり、同じ次元の異なるユニット間の変換を可能にします。しかし、私はそれを使用していないと私はそれが安定しているかどうかわからない。公平に、今日はそれをインストールしようとしましたが、インストールが失敗した...最初のHaskellの中のユニットを執行について

1

チェックhaskell.org wikipage:

https://wiki.haskell.org/Physical_units

あり、複数のオプションがありますが、私はありませんあなたが言及した「単位の単位」に類似したものが実際にあるかどうか確かめてください。

4

OK。私はその質問が古すぎることを知っています。しかし、Haskellで測定単位機能を提供するためのGHCプラグインビルドがあります。このAdam Gundryのpaperを参照してください。

0

私は学習に興味があり、まだF#の中学生ですが、ハスケルはよくわかりませんが、一般的な解決策は、数値をスカラーのタプルと単位を表すラベル、M)。例えば

は、尺度がNの数であり、Mstringあるmeasure<N,M>の一般的なタプルであるせ、次いで=, +, -, *, /, ^は、所与の測定、a, b, and c、スカラーp、ブールK、およびメジャーラベルの評価を実施するためにオーバーロードすることができます私はあなたがして、変換ベースの比較を行うためにオードと式のために独自のインスタンスを作成するための独自の通貨型クラスを作成する必要があるだろうと思うだろうな

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 
.... 
+1

これは、型システムを使用して静的にユニットを含む計算を検証するという問題を実際には解決しません元気です。 – dfeuer

関連する問題