F#铸造和泛型
试图学习一些F#,我遇到了几个hangups。F#铸造和泛型
下面的代码:
#light
module HtmlModule
type HtmlString(text:string) =
override x.ToString() = text
type HtmlAttribute(key:string, value:string) =
inherit HtmlString(key + "=\"" + value + "\"");
type HtmlElement(tag: string, ?contents:list<'a> when 'a :> HtmlString) =
inherit HtmlString("")
let innerContents = defaultArg contents []
let castToHtmlAttribute (hs:HtmlString) : Option<HtmlAttribute> =
match hs with
| :? HtmlAttribute as temp -> Some(temp)
| _ -> None
member x.tag = tag
member x.contents = innerContents |> List.filter(fun x -> (castToHtmlAttribute x).IsNone)
member x.attributes = innerContents |> List.map(fun x -> (castToHtmlAttribute x)) |> List.filter(fun x-> x.IsSome) |> List.map(fun x->x.Value)
override x.ToString() =
let sb = System.Text.StringBuilder()
sb.Append("<" + x.tag)
for att in x.attributes do
sb.Append(" " + att.ToString())
sb.Append(">")
for item in x.contents do
sb.Append(item.ToString())
sb.Append("</" + x.tag + ">")
sb.ToString()
let element tag contents = new HtmlElement(tag, contents)
let div contents = element "div" contents
let p contents = element "p" contents
let text text = new HtmlString(text)
let attr key value = new HtmlAttribute(key, value)
let classes value = attr "class" value
和快速的控制台程序,以显示该问题:
#light
open HtmlModule
let stuff = [for a in 1 .. 10 do yield p [text ("some String " + a.ToString())]]
let elem = div [
attr "class" "someClass";
text "This is some inner text";
div stuff;
]
let result = elem.ToString()
printfn "%A" result
编译器将不允许行
div stuff;
它指出:
"Error 7 Type mismatch. Expecting a HtmlString list but given a HtmlElement list The type 'HtmlString' does not match the type 'HtmlElement'"
这个问题可以跟踪到castToHtmlAttribute
方法签名
let castToHtmlAttribute (hs:HtmlString) : Option<HtmlAttribute> =
如果我做像这样这条线比较通用:
let castToHtmlAttribute (hs:'a when 'a :> HtmlString) : Option<HtmlAttribute> =
我得到一个新的错误:
"Error 2 This runtime coercion or type test from type 'a to HtmlAttribute involves an indeterminate type based on information prior to this program point. Runtime type tests are not allowed on some types. Further type annotations are needed."
任何帮助表示赞赏。
Expecting a HtmlString list but given a HtmlElement list The type 'HtmlString' does not match the type 'HtmlElement'"
这说明问题很好。对于F#,List<HTMLElement>
不是List<HTMLString>
,比如List<Orange>
是List<Fruit>
。
如果是这样,你可以写
Apple :: oranges
因为这没有任何意义,F#希望你投垂头丧气明确。请告诉div
使用通用列表。
总之,您可以将类型HTMLString list
更改为多态性#HTMLString list
或手动转换参数或stuff
。
贾斯汀,看看这篇文章:http://*.com/questions/1883246/none-pure-functional-code-smells/1884256#1884256 :)好吧,与被说,我会建议重写你的数据模型是这样的:http://pastebin.com/f27045779 – Juliet 2009-12-12 19:56:38
感谢您的链接,这有助于很多。我有点认为我做的事情完全错了。 :) – justin 2009-12-12 20:28:12