12

日付が存在する必要があるが、秒単位の時間部分はオプションであるDateTimeタイプについて考えてみます。時間の部分がある場合は、オプションのミリ秒の部分もある可能性があります。ミリ秒が存在する場合は、ナノ秒の部分もある可能性があります。

これに対処する方法はたくさんあります。例:

--rely on smart constructors 
data DateTime = DateTime { days:: Int, 
                           sec :: Maybe Int, 
                           ms :: Maybe Int, 
                           ns :: Maybe Int 
                         }

-- list all possibilities
data DateTime = DateOnly Int 
              | DateWithSec Int Int
              | DateWithMilliSec Int Int Int
              | DateWithNanoSec Int Int Int Int    

-- cascaded Maybe
data DateTime = DateTime Int (Maybe (Int, Maybe (Int, Maybe Int)))

-- cascaded data
data Nano = NoNano | Nano Int
data MilliSec = NoMilliSec | MilliSec Int Nano
data Sec = NoSec | Sec Int MilliSec
data Date = Date Int Sec

どの構成を使用しますか(もちろん、上記の例に限定されません)、そしてその理由は何ですか?

【意図】

ガイドラインとしてdate4jを使用して、Frege(http://code.google.com/p/frege/DateTime )で日付型の可能性を探っています(Haskellの日付と時刻のライブラリは非常に複雑でjava.util.Date壊れているため) )。私の現在のおもちゃの実装では、すべてのフィールドが必須ですが、もちろん、ユーザーを不要な精度から解放すると便利です(元の実装にはオプションのフィールドがあります)。

したがって、主な目標は次のとおりです。

  • 安全性:違法な状態は絶対に避けなければなりません
  • 利便性:タイプを操作するのは簡単である必要があります。たとえば、パターンマッチングはクールで、カレンダーの計算は簡単である必要があります...

それほど重要ではありません:

  • パフォーマンス:もちろん、このタイプでの作業は遅すぎるべきではありませんが、通常の使用法では、最後のクロックサイクルを絞り出す必要はありません。
  • メモリ:これが本当に重要な場合は、よりコンパクトなストレージ形式を簡単に導き出すことができます
  • 簡潔な実装:これはライブラリであり、スムーズにするために必要なすべてのコードを追加したいと思います。

とは言うものの、これはすべて非常に暫定的なものであり、あまり深刻に受け止めるべきではありません。

4

4 に答える 4

8

「違法な状態は何としてでも回避しなければならない」と「パターン マッチングがクールだろう」は、この場合、互いに真っ向から対立する優れた原則です。

さらに、日付と時刻は、多くのエッジケースと不規則なコーナーを備えた、危険な人間の文化的構成要素です。それらは、型システムで簡単にエンコードできるような規則ではありません。

したがって、この場合、不透明なデータ型、スマート コンストラクター、スマート デコンストラクターを使用します。パターン マッチングを使用したい場合に備えて、常にビュー パターンとパターン ガードがあります。

(また、依存するオプション データを動機付け要因として説明することさえしていません。)

于 2012-04-13T07:56:46.653 に答える
3

@dbauppのソリューションに触発されて、ファントムタイプのバージョンを候補に追加したいと思います。

-- using EmptyDataDecls
data DayPrec 
data SecPrec 
data MilliPrec 
data NanoPrec 

data DateTime a = DateTime { days :: Int, sec :: Int, ms :: Int, ns :: Int } 

date :: Int -> DateTime DayPrec
date d = DateTime d 0 0 0

secDate :: Int -> Int -> DateTime SecPrec
secDate d s = DateTime d s 0 0

...    

--will work only for same precision which is a Good Thing (tm)
instance Eq (DateTime a) where
  (DateTime d s ms ns) == (DateTime d' s' ms' ns') = [d,s,ms,ns] == [d',s',ms',ns'] 

私が間違っていなければ、これにより1つのタイプで作業できますが、必要に応じて精度を区別できます。しかし、私はいくつかの欠点もあると思います...

于 2012-04-13T08:39:34.910 に答える
0

(より一般的な問題とは対照的に) この問題のみを解決したいと仮定すると、10 進ライブラリーが必要な場合があります。

于 2012-04-13T16:53:37.707 に答える