Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# 避免使用Option.Value_F#_Idioms - Fatal编程技术网

F# 避免使用Option.Value

F# 避免使用Option.Value,f#,idioms,F#,Idioms,我有这样一种类型: type TaskRow = { RowIndex : int TaskId : string Task : Task option } 函数返回要进一步处理的这些记录的列表。执行该处理的某些函数仅与TaskRow项目相关,其中Task是Some。我想知道最好的办法是什么 天真的做法是这样做的 let taskRowsWithTasks = taskRows |> Seq.filter (fun row

我有这样一种类型:

type TaskRow =
    {
        RowIndex : int
        TaskId : string
        Task : Task option
    }
函数返回要进一步处理的这些记录的列表。执行该处理的某些函数仅与
TaskRow
项目相关,其中
Task
Some
。我想知道最好的办法是什么

天真的做法是这样做的

let taskRowsWithTasks = taskRows |> Seq.filter (fun row -> Option.isSome row.Task)
并将其传递给这些函数,只需假设
Task
永远不会是
None
,然后使用
Task.Value
,如果我不传递一个特殊列表,就有可能出现NRE。这正是当前的C代码所做的,但对于F代码来说,这似乎有点不符合实际。我不应该“假设”事情,而是让编译器告诉我什么是可行的

更具“功能性”的做法是,每次值相关时进行模式匹配,然后对
None
不执行/不返回任何操作(并使用
choose
或类似操作),但这似乎是重复和浪费的,因为同一项工作会重复多次

另一个想法是引入第二种稍微不同的类型:

type TaskRowWithTask =
    {
        RowIndex : int
        TaskId : string
        Task : Task
    }
然后,原始列表将被过滤到这种类型的“子列表”中,以便在适当的情况下使用。我想从功能的角度来看这是可以的,但我想知道是否有一种更好的、惯用的方式,而不必求助于这种“助手类型”


谢谢你的指点

我同意你的观点,更“纯功能”的方法是重复模式匹配,我的意思是使用带有
Seq的函数。选择进行过滤的
,而不是将其保存到另一个结构中

let tasks = Seq.choose (fun {Task = t} -> t) taskRows

问题在于性能,因为它会被多次计算,但您可以使用
Seq.cache
,这样在后台它会被保存到一个中间结构中,同时让您的代码看起来更“纯功能化”。

知道任务已经被过滤,这有很大的价值,因此,有两种不同的类型可能会有所帮助。而不是定义两种不同类型(在F中,这不是很大的交易),也可以考虑定义一个通用的<代码>行< /代码>类型:

type Row<'a> = {
    RowIndex : int
    TaskId : string
    Item : 'a }

如果初始
taskRows
值的类型为
seq
,则生成的
taskRowsWithTasks
序列的类型为
seq

为什么不
seq。选择project
而不是
map
+
选择id
?是的,确实如此,为什么不呢?因为我没有想到它,这就是为什么,但显然,它更简单:)
let project = function
    | { RowIndex = ridx; TaskId = tid; Item = Some t } ->
        Some { RowIndex = ridx; TaskId = tid; Item = t }
    | _ -> None

let taskRowsWithTasks =
    taskRows
    |> Seq.map project
    |> Seq.choose id