【问题标题】:internal representation not hidden in f# module内部表示未隐藏在 f# 模块中
【发布时间】:2019-04-02 06:59:19
【问题描述】:

我正在做一个项目,使用模块,我计算图像并将它们打印在屏幕上

我的代码中的所有东西都可以正常工作,但我对这种不便之处不太满意:在我的 .fs 文件(我定义类型和所有函数的地方)我已经声明了

type Picture = P of (Set<((float*float)*(float*float))> * (int*int))

集合描述图片中线段的点(线) 并且需要一对 int 来定义将显示图像的边界框(宽度和高度)

当我尝试我的函数(在另一个文件中)时,我使用我的网格函数

let rec setBuilder (ls:((int*int)*(int*int)) list) = 
match ls with
| [] ->  Set.empty
| ((x,y),(w,z))::xs -> setBuilder xs |> Set.add ((float x,float y),(float w, float z)) 

let grid ls (wdt,hgt) = P (setBuilder ls, (wdt, hgt)) 

有了这个,我需要一个情侣/情侣 int 列表并构建我的图片

问题是,当我用网格构建图片时(在我尝试所有功能的另一个文件中)是可见的内部表示

let persn = [((4, 0),(6, 7));  ((6, 7), (6, 10));  ((6, 10), (0, 10));  ((0, 10), (0, 12));   ((0, 12), (6, 12));   ((6, 12), (6, 14));   ((6, 14), (4, 16));   ((4, 16), (4, 18));   ((4, 18), (6, 20));  ((6, 20), (8, 20));
        ((8, 20), (10,18));   ((10, 18), (10, 16));   ((10, 16), (8, 14));   ((8, 14), (8, 12));   ((8, 12), (10, 12));   ((10, 12), (10, 14));   ((10, 14), (12, 14));   ((12, 14), (12, 10));   ((12, 10), (8, 10));   ((8, 10), (8, 8));
        ((8, 8), (10, 0));   ((10, 0), (8, 0));   ((8, 0), (7, 4));   ((7, 4), (6, 0));   ((6, 0), (4, 0))]

let box = (15,20)

let person = grid persn box

当我解释从控制台得到的最后一行时

val person : Picture =
P (set
[((0.0, 10.0), (0.0, 12.0)); ((0.0, 12.0), (6.0, 12.0));
((4.0, 0.0), (6.0, 7.0)); ((4.0, 16.0), (4.0, 18.0));
((4.0, 18.0), (6.0, 20.0)); ((6.0, 0.0), (4.0, 0.0));
((6.0, 7.0), (6.0, 10.0)); ((6.0, 10.0), (0.0, 10.0));
((6.0, 12.0), (6.0, 14.0)); ...], (15, 20))

有一种方法可以隐藏这些信息,我查了一下,解决方案似乎是标记值(但我已经在使用它们了)

* 编辑 *

我注意到这种行为可能与我的实现文件中的静态成员相关联,没有它们,内部类型不会显示

type Picture with
 static member(*)  (c:float,pic:Picture) =
        match pic with 
        | P(set,(wdt,hgt)) ->  P (Set.map (fun ((x,y),(w,z)) -> ((x*c,y*c),(w*c,z*c))) set, (int (round (float wdt * c)) ,int (round (float hgt * c))))   


 static member(|>>)  (pic1:Picture,pic2:Picture) =
        match pic1,pic2 with
         (P (set1,(w1,h1)), P (set2,(w2,h2))) ->   let new_p2 = (((float h1/ float h2)) * pic2) 
                                                   match new_p2 with 
                                                   P (nset2,(nw2,nh2)) -> P(Set.union set1 (Set.map (fun ((x,y),(w,z)) -> ((x + (float w1) ,y),(w + (float w1), z)) ) nset2),(w1 + nw2, h1)) 


 static member(|^^)  (pic1:Picture,pic2:Picture) =
        match pic1,pic2 with
        (P (set1,(w1,h1)), P (set2,(w2,h2))) ->  let new_pic2 = (((float  w1/ float w2)) * pic2)
                                                 match new_pic2 with
                                                 P (nset2,(nw2,nh2)) -> P(Set.union set1 (Set.map (fun ((x,y),(w,z)) -> ((x,(float h1) + y),(w,(float h1) + z)) ) nset2),(w1 , h1 + nh2))

 static member (>||>) (n, pic:Picture) =
        match n with
        | 0 ->  pic
        | m ->  pic |>> ((m-1) >||> pic)


 static member (^||^) (n, pic:Picture) =
      match n with
      | 0 -> pic
      | m -> pic |^^ ((m-1) ^||^ pic) 

【问题讨论】:

  • 在函数式编程中,您通常不会隐藏数据的内部表示。为什么要隐藏它?纯粹是为了使用 FSI 时的方便,还是因为您希望如何构建程序?
  • 如果您希望 FSI 不显示最后一个表达式的值,您可以随时添加另一个表达式,例如 ()。调用 fsi.exe 时还有一个 --quiet 选项,它会抑制所有输出,除非您明确打印出来。
  • 我希望隐藏类型,因为这是练习的要求
  • 是什么让你觉得它没有隐藏?
  • 我知道它已显示,因为当我尝试在单独的文件中使用我的函数时(在这种情况下,我是一个不知道我如何设法实现我的 .fsi 文件的用户)和用我的网格函数创建一个图片,在解释器控制台中它告诉我 P 是一对 (set + (int, int))

标签: module f# internals representation


【解决方案1】:

只要写type Picture = private P of ...,其他模块就看不到Picture的内部了。

注意:如果写type private Picture = P of ...,表示其他模块看不到Picture类型。

【讨论】:

  • 嗯,这很奇怪。请查看我的演示代码here。如果private 关键字在那里,我们会遇到编译器错误,因为我们正在尝试从其他模块访问类型的内部。删除关键字然后错误消失。也许你的 F# 版本太旧了?
  • 我会尽快尝试,可能是版本,昨天我更新了 monodevelop,但在此之前我运行的是今年 3 月下载的版本
猜你喜欢
  • 2021-12-23
  • 2011-11-11
  • 1970-01-01
  • 2020-03-08
  • 2021-11-25
  • 2013-05-07
  • 1970-01-01
  • 2015-07-16
  • 1970-01-01
相关资源
最近更新 更多