为什么F#不喜欢输入类型(“列表列表”)?

时间:2019-12-01 21:04:36

标签: f#

*我编辑了原始帖子以包含更多信息。

我正在处理F#分配,在该分配中,我应该创建一个将“任何列表列表”作为输入并输出“任何列表”的函数。它应该能够将列表列表串联为一个列表。

这是我的功能:

var dd = {
    content: [
        {
            columns: [
                {
                    text: 'Column 1',
                    style: [{bold: true, alignment: 'center'}],
                    width: 45
                },
                [
                    {
                        text: 'Column 2',
                        style: [{bold: true, alignment: 'center'}],
                        width: 200 // Nothing changes..
                    },
                    {
                        columns: [
                            {
                                text: 'A',
                                width: '*',
                                style: [{bold: true, alignment: 'center'}],
                            },
                            {
                                text: 'B',
                                width: '*',
                                style: [{bold: true, alignment: 'center'}],
                            }
                        ]
                    }
                ],
                {
                    text: 'Column 3',
                    width: '*',
                    style: [{bold: true, alignment: 'center'}],
                }
            ]
        }   
    ]
}

此解决方案或多或少直接从Microsoft的使用List.concat函数的示例复制而来,唯一的例外是输入/输出类型的规范。

运行代码时出现此错误:

let llst = [ [1] ; [2;3] ; ['d';'e';'f'] ]
let concat (llst:'a list list) : 'a list = 
    List.concat llst

List.iter (fun elem -> printf "%d " elem) concat

所以看来concat正在将我的第一个字符列表变成我不理解的字符。

任何人都可以帮助我理解为什么会出现此类型错误以及如何编写具有所需类型的函数吗?

2 个答案:

答案 0 :(得分:3)

问题出在concat函数的实现中。很难说出完全看不到代码的位置,但是由于这是一项任务,实际上最好解释一下错误消息告诉您的内容,以便您自己找到问题。

错误消息告诉您F#类型推断算法在代码中找到了一个位置,在该位置您编写的内容的实际类型与该位置中预期的类型不匹配。它还告诉您两种不匹配的类型是什么。例如,假设您编写了这样的内容:

let concat (llst:'a list list) : 'a list = 
  llst

由于第二行上的错误,您将得到错误,因为llst的类型为'a list list(编译器从您在第一行给出的类型注释中知道了这一点) type与'a list的函数结果类型相同-也是由类型注释指定的。

因此,为了帮助您找到问题-查看出现错误的确切位置,并尝试推断出编译器认为实际类型为'a list list的原因,并尝试理解为什么期望{{1 }}作为该位置的类型。

答案 1 :(得分:0)

这是正确的:

let concat (llst:'a list list) : 'a list = 
    List.concat llst

但是,它实际上等效于let concat = List.concat

但是,这不能编译,列表中的元素必须是同一类型:

let llst = [ [1] ; [2;3] ; ['d';'e';'f'] ]

这也是有问题的:

List.iter (fun elem -> printf "%d " elem) concat

List.iter有两个参数,第二个参数必须是List。但是,根据您的情况,您(根据编译器错误)提供的concat函数是a' List List -> a' List

我怀疑您打算做的是先将concat函数应用于您的llist

List.iter (fun elem -> printf "%d " elem) (concat llist)
// or
llist
|> concat
|> List.iter (fun elem -> printf "%d " elem)

但是,所有这些可能都缺少练习的重点。也许您需要做的就是基于列表的空/非空状态实现一些简单的递归。从这里填空:

let rec myconcat acc inlist =
    match inlist with
    | [] -> ??
    | elt :: tail -> ??