List F#列表拆分,拆分

List F#列表拆分,拆分,list,split,f#,divide,List,Split,F#,Divide,我在试着解决F#中的一个练习。我必须编写一个代码来区分一本书和一部电影,并将其作为一本书或一部电影放在列表中。它可以通过文件大小区分两者,因为书籍没有文件大小。例如,如果我放入一本书,代码必须将它作为一本书和电影添加到列表中。我将示例结果与输入链接起来。先谢谢你 type Movie = { movieName: string duration: Nat fileSize: Nat } type Book = { bookName: string

我在试着解决F#中的一个练习。我必须编写一个代码来区分一本书和一部电影,并将其作为一本书或一部电影放在列表中。它可以通过文件大小区分两者,因为书籍没有文件大小。例如,如果我放入一本书,代码必须将它作为一本书和电影添加到列表中。我将示例结果与输入链接起来。先谢谢你

type Movie =
    { movieName: string
      duration: Nat
      fileSize: Nat }

type Book =
    { bookName: string
      pages: Nat }

type Activity =
    | Watch of Movie
    | Read of Book


let rec createActivities(hl: (string * Nat * Nat) list): Activity list = 
    match hl with
      | [] -> []
      | x::xs -> ....
以下是输入:

createActivities([
                "The Hobbit"                , 304N, 0N
                "The Fellowship of the Ring", 228N, 50N
                "The Name of the Wind"      , 662N, 0N
                "The Emoji Movie"           , 86N , 1024N
                "The Hobbit"                , 164N, 9001N
                "The Fellowship of the Ring", 700N, 0N
结果:

[
                Read { bookName = "The Hobbit"; pages = 304N }
                Watch { movieName = "The Fellowship of the Ring"; duration = 228N; fileSize = 50N }
                Read { bookName = "The Name of the Wind"; pages = 662N }
                Watch { movieName = "The Emoji Movie"; duration = 86N; fileSize = 1024N }
                Watch { movieName = "The Hobbit"; duration = 164N; fileSize = 9001N }
                Read { bookName = "The Fellowship of the Ring"; pages = 700N }
            ]
F#中的匹配表达式可以非常高级,在匹配表达式的各个部分中都有子匹配。例如,匹配表达式中的
x::xs
大小写可以转换为
(名称、持续时间、文件大小)::xs
。如果您为其中一个指定了一个值,那么它将仅在元组的该部分具有该值时匹配。考虑到这一点,我将把你的匹配表达式写成如下:

let rec createActivities(hl: (string * Nat * Nat) list): Activity list = 
    match hl with
      | [] -> []
      | (name, pages, 0N) :: xs -> Read { bookName = name; pages = pages } :: createActivities xs
      | (name, duration, fileSize) :: xs -> Watch { movieName = name; duration = duration; fileSize = fileSize } :: createActivities xs

其工作原理是,将按照从上到下的顺序处理
匹配
案例,并使用第一个匹配的案例。因此,如果元组作为
0N
作为其第三个元素,则将使用第二个匹配大小写,否则将使用第三个匹配大小写。因此,匹配表达式可以保持非常简单和干净的外观。

我可以这样解决问题。谢谢你的帮助

let rec createActivities(hl: (string * Nat * Nat) list): Activity list =    
  match hl with 
  | [] -> []
  | (name, pagesorduration, Size) :: xs -> 
    if Size = 0N then Read { bookName = name; pages = pagesorduration } :: createActivities(xs) 
    else Watch { movieName = name; duration = pagesorduration; fileSize = Size } :: createActivities xs

你能解释一下你在挣扎什么吗?我想您想用实际实现替换
createActivities
中的
——您想在那里实现什么逻辑?我想使用递归逻辑。谢谢您的帮助。我对它进行了测试,但它在“0N”处掉了一个错误。错误:“非原始数字文本常量不能在模式匹配中使用,因为它们可以通过使用数字文字模块映射到多个不同类型。请考虑使用变量替换,并在匹配子句的末尾使用‘Time=’。”然后您需要使用F#的内置
int
类型,而不是
Nat
。或者,如果您确实想使用
Nat
,则按照错误消息的建议执行,并使用
when
子句。例如,
|(名称、页面、零)::xs when zero=0N->Read{…}
多亏了你的帮助,我可以解决这个问题。我用if更改了代码。