2012-06-24 72 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]