2012-06-24 71 views
7

在F#中的序列/數組我可以很容易做到F#生成日期

let a = [1 .. 10];; 

那麼我爲什麼不能做

let a = DateTime.Parse("01/01/2012") 
let b = DateTime.Parse("01/01/2020") 


let dateList = [a .. b] 

它給出了一個錯誤Type constraint mismatch. The type DateTime is not compatible with type TimeSpan

回答

14

有兩種問題 - 首先,您需要指定要在列表元素之間使用的時間間隔。這將是一個TimeSpan,但它沒有靜態的Zero成員。

type TimeSpanW = { span : TimeSpan } with 
    static member (+) (d:DateTime, wrapper) = d + wrapper.span 
    static member Zero = { span = new TimeSpan(0L) } 

您:

這個約束是由要求「步」類型具有靜態(+)Zero成員

您可以定義自己的結構,但是它支持所需的操作skip range operator要求可以這樣做:

let ts = new TimeSpan(...) 
let dateList = [a .. {span = ts} .. b] 

編輯:下面是使用可識別聯合替代語法,您可能希望:

type Span = Span of TimeSpan with 
    static member (+) (d:DateTime, Span wrapper) = d + wrapper 
    static member Zero = Span(new TimeSpan(0L)) 

let ts = TimeSpan.FromDays(1.0) 
let dateList = [a .. Span(ts) .. b] 
+0

工程很漂亮...有沒有鏈接解釋發生了什麼?爲什麼零是必需的?還有(+)運算符。 –

+0

@KnowsNotMuch - 這是「跳過範圍」操作符所要求的 - 我已通過鏈接更新了答案。 – Lee

+1

@KnowsNotMuch - 實際發生的事情 - 步驟必須從0開始,然後增加 - 如果您查看簽名,則步驟不必具有與端點相同的類型。 –

11

這裏的生成日期列表的時髦方式。請注意,因爲我從其他人那裏獲得了這個信息,所以我不記得這一點。

open System 
let a = new DateTime(2013,12,1) 
let b = new DateTime(2013,12,5) 
Seq.unfold (fun d -> if d < b then Some(d, d.AddDays(1.0)) else None) a 
|> Seq.toList;; 

它返回:

VAL它:DateTime的列表= [2013年1月12日00:00:00; 02/12/2013 00:00:00; 03/12/2013 00:00:00; 04/12/2013 00:00:00]