我定义了一个类型
type 'a sexp =
| E of 'a
| T of ( sexp<'a> * sexp<'a> );;
示例:
( "这个". (("是". "a") . ( "s". "表达式")) )
是字符串的 sexp。
( ( 1 . 5 ) . 2 )
是 int 的 sexp。
<小时/>我创建了一个函数 tolist,给定一个表达式,返回一个具有以下格式的列表。
let rec tolist expr =
match expr with
| Null -> [" "]
| E(x) -> [string x]
| T(l,r) ->
let l = tolist l
let r = tolist r
["("]@(l)@[" . "]@(r)@[")"];;
val tolist : expr:obj sexp -> 字符串列表
我的问题是我想要“a sexp”,而不是像告诉我的那样“obj sexp”。我哪里做错了?
调用就是这样 tolist (T(E("this") , E("is")));;
最佳答案
string
F# 中的函数的类型为 obj -> string
,所以它限制了 x
的类型在你的E(x)
成为obj
。 (更新:比这稍微复杂一些;有关所有详细信息,请参阅 this answer 的后半部分。但它归结为“string
需要在编译时知道其参数的具体类型时间,这样它就可以调用正确的 .ToString()
方法。如果你向它传递一个泛型类型,那么它可以确定唯一可以工作的具体类型是 obj
,所以它最终会受到限制你的泛型类型为 obj
。”)而这反过来又限制了你的 tolist
的类型函数为sexp<obj>
(或obj sexp
——相同类型,不同的书写方式)。
如果替换string
调用 sprintf "%A"
相反,你的函数将是适当通用的。例如,您希望代码如下所示:
type 'a sexp =
| E of 'a
| T of ( sexp<'a> * sexp<'a> )
let rec tolist expr =
match expr with
| Null -> [" "]
| E(x) -> [sprintf "%A" x]
| T(l,r) ->
let l = tolist l
let r = tolist r
["("]@(l)@[" . "]@(r)@[")"]
关于list - F# 类型 obj 但我想要 'a,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43248914/