文献资料的示例代码使用List._item定义了_pageNumber,但我似乎找不到使用它的示例。我尝试了下面的代码,但是它出现了一个错误。
view (Book._pageNumber 1) rayuela // error它将如何使用?
发布于 2022-05-15 07:05:01
Brian的回答从技术角度看是非常准确的,但在概念上忽略了最重要的一点:您正在“观看”一个部分透镜(也称为棱镜),而不是“预览”它。这不是F#+的限制,这只是镜头的表现。
一些背景:棱镜或部分透镜就像一个可能失败的镜头,所以原则上你不能对它们使用view操作,因为这是一个总是成功的操作,或者更好的说,不考虑失败,您应该使用返回选项的preview操作。
构图规则规定作曲的结果:
这就是,一旦合成链中有棱镜,结果就是棱镜。
在我们的例子中,_pages << List._item i << _Some是由_Some (棱镜)组成的透镜,因此_pageNumber i将是棱镜。
现在,如果您使用视图作为棱镜,会发生什么?zero值表示失败,例如,选项的零值为None,但这里没有指定零值。
Brian是对的,错误信息具有误导性,更好的错误是“不要在棱镜上使用视图”,但是所发生的事情是尝试获取一个可以用zero表示失败的裸值(而不是在选项内)。
TL;博士
改为使用:
preview (Book._pageNumber 1) rayuela // Some { Contents = "The End" }有人应该发送一个PR添加到文档中。
发布于 2022-05-14 04:22:27
我也看到了同样的事情:
没有重载匹配的方法‘零’“。
这个问题是由_Some镜头引起的,它不适用于记录类型,因为它们没有默认值(即“零”)值:
let inline _pageNumberOpt i b =
_pages << List._item i <| b
let pageOpt = view (_pageNumberOpt 1) rayuela // this is fine
let page = view _Some pageOpt // this doesn't work, because the input is an Option<Page>
let x = view _Some (Some 1) // this works, because the input is an Option<int>这似乎是FSharpPlus中的一个限制,文档中没有考虑到这个限制。如果您想解决这个问题,您可以自己定义Page.Zero,然后这个示例将编译:
type Page =
{ Contents: string }
static member Zero = { Contents = "" }
let page = view (Book._pageNumber 1) rayuela
printfn $"{page}" // output is: { Contents = "The End" }
let noPage = view (Book._pageNumber 5) rayuela
printfn $"{noPage}" // output is: { Contents = "" }只有当您请求一个不存在的页面时,Page.Zero才会被调用,但是在任何情况下它都需要编译器在那里。
(FWIW,据我的经验,FSharpPlus是一只非常非常精致的野兽。这是一个有趣的实验,但很容易破裂。当它崩溃时,编译器的错误令人难以置信。)
https://stackoverflow.com/questions/72237070
复制相似问题