Idrisを探索する私の旅では、私は小さな日付処理モジュールを "慣用的な"方法で書こうとしています。ここまで私がこれまで持っていたことがあります。日付を計算するときにFin nとIntegerを正しく処理する方法は?
まず私は日、月、年を表現するためにいくつかの基本的な種類があります:
module Date
import Data.Fin
Day : Type
Day = Fin 32
data Month : Type where
January : Month
February : Month
....
toNat : Month -> Nat
toNat January = 1
toNat February = 2
...
data Year : Type where
Y : Integer -> Year
record Date where
constructor MkDate
day : Day
month : Month
year : Year
私はDate
に日のいくつかの番号を追加する機能addDays
を実装したいと思います。このため私は、次の補助関数を定義した:私は、現在では日の追加数はフィット非常に基本的なケースで立ち往生しています
addDays : Date -> Integer -> Date
addDays (MkDate d m y) days =
let maxDays = daysInMonth m y
shiftedDays = finToInteger d + days
in case integerToFin shiftedDays (finToNat maxDays) of
Nothing => ?hole_1
Just x => MkDate x m y
:
isLeapYear : Year -> Bool
isLeapYear (Y y) =
(((y `mod` 4) == 0) && ((y `mod` 100) /= 0)) || ((y `mod` 400) == 0)
daysInMonth : Month -> Year -> Day
daysInMonth January _ = 31
daysInMonth February year = if isLeapYear year then 29 else 28
daysInMonth March _ = 31
...
そして最後には、としてaddDays
を定義しよう月の期間。
Date.idrでaddDaysでDate.caseブロックの右側のチェック:92:11期待されるタイプ 日でこれが原因のタイプの不可解さ
When checking argument day to constructor Date.MkDate:
Type mismatch between
Fin (finToNat maxDays) (Type of x)
and
Day (Expected type)
Specifically:
Type mismatch between
finToNat maxDays
and
32
ここでは、コンパイラの出力がありますmaxDays
は、明らかにDay
である必要があります。単純にFin 32
です。
私は、これは、それ自体がInteger
タイプにmod
の非全体から来てisLeapYear
の非全体から茎daysInMonth
の非全体に関連するかもしれないと思います。
おかげでたくさん!私は実際に日付を使って働くことを知っています*と*時間は非常に難しく、大きな危険を伴います。私はレッスンを学ぶためにタイムゾーンの問題で十分に噛まれました。私の野心はもっと控えめで、日々の仕事は、私が取り組んでいる別の問題を引き起こしたヤク剃り運動として浮上しました。私の野望は本格的な日付ライブラリー(まだではない)を作成するのではなく、実行可能で興味深い「日付」タイプを持つことです – insitu
他のSOの質問へのリンクもありがとうございます:https:// forge .ocamlcore.org/scm/viewvc.php/trunk/calendarFAQ-2.6.txt?view =マークアップ&ルート=カレンダー – insitu