为什么我不能创建通用函数?

时间:2017-03-04 20:22:22

标签: generics types f#

在下面的代码中,编译器假定参数r的类型为Rec2。由于类型Rec1具​​有函数定义中使用的所有字段,因此可以使用函数注释创建其中r为Rec1类型的函数。到目前为止,非常好。

但我希望r成为另一种类型,比如说' a。不幸的是,我不知道' a是什么。所以我尝试创建一个泛型函数,其中r是泛型类型。下面的代码显示编译器不允许我这样做。

有没有办法创建这样的通用函数?

type Rec1 = {A: int; B: string}
let r0 = {A = 0; B = "Hello"}
type Rec2 = {A: int; B: string; C: float}

let f2 (x, r) = {A = r.A; B = r.B; C = x}
// val f2 : x:float * r:Rec2 -> Rec2
let f1 (x, (r: Rec1)) = {A = r.A; B = r.B; C = x}
// val f1 : x:float * r:Rec1 -> Rec2
let g<'T> (x, (r: 'T)) = {A = r.A; B = r.B; C = x}
(* error FS0193: Type constraint mismatch. The type 
    'T    
is not compatible with type
    Rec2    
The type ''T' does not match the type 'Rec2' *)

1 个答案:

答案 0 :(得分:2)

评论显示您实际上正在使用CSVProvider,这意味着您不需要这样做。您已经进行了静态输入:

使用FSharp.Data文档中的示例csv文件:

  

日期,开盘价,最高价,最低价,收盘价,成交量,收盘价   2012-01-27,29.45,29.53,29.17,29.23,44187700,29.23   2012-01-26,29.61,29.70,29.40,29.50,49102800,29.50   2012-01-25,29.07,29.65,29.07,29.56,59231700,29.56   2012-01-24,29.47,29.57,29.18,29.34,51703300,29.34

只需使用type Stocks = CsvProvider<"test.csv"> type Rec2 = {Open: decimal; Close: decimal; Extra: string} let openCloseWithExtra (stockRow : Stocks.Row) = {Open = stockRow.Open; Close = stockRow.Close; Extra = "extra"} 作为类型:

let inline anyOpenCloseWithExtra stockRow =
    let open' = ((^T) : (member Open : decimal) (stockRow))
    let close' = ((^T) : (member Close : decimal) (stockRow))
    {Open = open'; Close = close'; Extra = "extra"}

如果由于某种原因,您确实需要使用暴露两个属性的完全任意类型,则可以使用静态解析的类型参数来执行此操作:

SQL> ed
Wrote file afiedt.buf

  1  select A.COLUMN_LABEL,B.HOST_NAME AS HOST,B.TARGET_NAME AS DATABASE,B.STATU
S AS CURRENT_STATUS, B.TABLESPACE_NAME AS TS_NAME,round(sum(B.file_size/(1024*10
24*1024)),2) AS CURRENT_SIZE,
  2  B.AUTOEXTENSIBLE AS TYPE_TS,case when autoextensible ='YES' then round(sum(
max_file_size/(1024*1024*1024)),2) ELSE NULL END AS TOTAL_MAX_SIZE,to_number(A.v
alue)/1024 as value
  3  FROM SYSMAN.MGMT$METRIC_CURRENT A,SYSMAN.MGMT$DB_DATAFILES_ALL B,sysman.mgm
t$db_tablespaces C
  4  where a.column_label in ( 'Tablespace Used Space (MB)')
  5      and a.target_type in( 'rac_database','oracle_database')
  6      and a.target_type =b.target_type
  7      AND A.TARGET_TYPE=C.TARGET_TYPE
  8      AND B.TARGET_TYPE=C.TARGET_TYPE
  9     AND B.STATUS IN('ONLINE')
 10    AND A.TARGET_NAME=B.TARGET_NAME
 11    AND A.TARGET_NAME=C.TARGET_NAME
 12    AND B.TARGET_NAME=C.TARGET_NAME
 13  GROUP BY 1,2,3,4,5,6,7,8
 14* ORDER BY 1,2,3,4,5,6,7,8
SQL> /
select A.COLUMN_LABEL,B.HOST_NAME AS HOST,B.TARGET_NAME AS DATABASE,B.STATUS AS
CURRENT_STATUS, B.TABLESPACE_NAME AS TS_NAME,round(sum(B.file_size/(1024*1024*10
24)),2) AS CURRENT_SIZE,
       *
ERROR at line 1:
ORA-00979: not a GROUP BY expression