Generics 铸造和仿制药
试图学习一些F#,我遇到了一些问题 代码如下:Generics 铸造和仿制药,generics,f#,casting,Generics,F#,Casting,试图学习一些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, ?cont
#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
编译器将不允许使用该行
div stuff;
它说:
“错误7类型不匹配。应为HtmlString列表,但给定HtmlElement列表,类型'HtmlString'与类型'HtmlElement'不匹配”
此问题可以跟踪到castToHtmlAttribute
方法签名
let castToHtmlAttribute (hs:HtmlString) : Option<HtmlAttribute> =
让castToHtmlAttribute(hs:HtmlString):选项=
如果我让这句话更通用,就像这样:
let castToHtmlAttribute (hs:'a when 'a :> HtmlString) : Option<HtmlAttribute> =
let castToHtmlAttribute(hs:'a when'a:>HtmlString):选项=
我得到一个新错误:
“错误2此从类型'a到HtmlAttribute的运行时强制或类型测试涉及基于此程序点之前的信息的不确定类型。不允许对某些类型进行运行时类型测试。需要进一步的类型批注。”
感谢您的帮助
应为HtmlString列表,但给定HtmlElement列表,类型“HtmlString”与类型“HtmlElement”不匹配
这很好地说明了这个问题。对于F#,列表
不像列表
那样是一个列表
如果是,你可以写
Apple :: oranges
因为这没有任何意义,F#希望您显式地使用downcast。只需告诉div
使用通用列表即可
简言之,您可以将类型HTMLString list
更改为多态的#HTMLString list
,或者手动强制转换参数或stuff
应为HtmlString列表,但给定HtmlElement列表,类型“HtmlString”与类型“HtmlElement”不匹配
这很好地说明了这个问题。对于F#,列表
与列表
不同,它不是一个列表
如果是,你可以写
Apple :: oranges
因为这没有任何意义,F#希望您明确地抛出downcast。只需告诉div使用通用列表即可
简而言之,您可以将类型
HTMLString list
更改为多态的#HTMLString list
,或者手动转换参数或内容。这里的诊断不是很好
您可以这样修复代码:
let stuff = [for a in 1 .. 10 do
yield (p [text ("some String " + a.ToString())]) :> HtmlString]
在这里,我插入了一个显式向上转换到基类型。这里的诊断不是很好
您可以这样修复代码:
let stuff = [for a in 1 .. 10 do
yield (p [text ("some String " + a.ToString())]) :> HtmlString]
我在基础类型中插入了一个显式的Up石膏。
我真的想要更多的API,而不是客户机代码必须被抛出。请考虑朱丽叶的建议。总的来说,大多数语言都很难编写包含列表和列表的代码,而不必在时间上显式地进行转换。我真的需要更多的API,而不是客户端代码。我们要考虑朱丽叶的建议。总的来说,在大多数语言中,编写既包含列表又包含列表的代码是很困难的,有时不必显式地强制转换。Justin,看看这篇文章:)好吧,话虽如此,我还是建议您这样重写数据模型:感谢链接,这很有帮助。我觉得我做的事情完全错了贾斯汀,看看这篇文章:)好吧,既然如此,我建议你这样重写你的数据模型:谢谢你的链接,这很有帮助。我觉得我做的事情完全错了