【问题标题】:Subtle type error微妙的类型错误
【发布时间】:2015-03-19 11:24:06
【问题描述】:

我是编程新手,F# 是我的第一个 .NET 语言。

我正在 Rosalind.info 上尝试this problem。基本上,给定一个 DNA 字符串,我应该返回四个整数,分别计算符号“A”、“C”、“G”和“T”在字符串中出现的次数。

这是我目前写的代码:

open System.IO
open System

type DNANucleobases = {A: int; C: int; G: int; T: int}

let initialLetterCount = {A = 0; C = 0; G = 0; T = 0}

let countEachNucleobase (accumulator: DNANucleobases)(dnaString: string) =
    let dnaCharArray = dnaString.ToCharArray()
    dnaCharArray
    |> Array.map (fun eachLetter -> match eachLetter with
                                    | 'A' -> {accumulator with A = accumulator.A + 1}
                                    | 'C' -> {accumulator with C = accumulator.C + 1}
                                    | 'G' -> {accumulator with G = accumulator.G + 1}
                                    | 'T' -> {accumulator with T = accumulator.T + 1}
                                    | _ -> accumulator)

let readDataset (filePath: string) =
    let datasetArray = File.ReadAllLines filePath 
    String.Join("", datasetArray)

let dataset = readDataset @"C:\Users\Unnamed\Desktop\Documents\Throwaway Documents\rosalind_dna.txt"
Seq.fold countEachNucleobase initialLetterCount dataset

但是,我收到以下错误消息:

CountingDNANucleotides.fsx(23,10):错误 FS0001:类型不匹配。 期待一个 DNANucleobases -> 字符串 -> DNANucleobases 但给定一个 DNANucleobases -> 字符串 -> DNANucleobases [] 'DNANucleobases' 类型与'DNANucleobases []' 类型不匹配

出了什么问题?我应该做出哪些改变来纠正我的错误?

【问题讨论】:

  • 我认为你的Array.map 应该是array.iter 并且你需要返回累加器
  • 你必须fold dnaCharArray 数组,因为countEachNucleobase 期望的累积值是DNANucleobases,而不是数组。

标签: types f#


【解决方案1】:

countEachNucleobase 返回一个累加器类型的数组,而不仅仅是它作为其第一个参数获得的累加器。因此,Seq.fold 无法为其'State 参数找到有效的解决方案:它只是输入上的记录,但输出上的数组。用于折叠的函数必须将累加器类型作为其第一个输入和输出。

代替问题代码中的Array.map,您已经可以使用Array.fold

let countEachNucleobase (accumulator: DNANucleobases) (dnaString: string) =
    let dnaCharArray = dnaString.ToCharArray()
    dnaCharArray
    |> Array.fold (fun (accumulator : DNANucleobases) eachLetter ->
        match eachLetter with
        | 'A' -> {accumulator with A = accumulator.A + 1}
        | 'C' -> {accumulator with C = accumulator.C + 1}
        | 'G' -> {accumulator with G = accumulator.G + 1}
        | 'T' -> {accumulator with T = accumulator.T + 1}
        | _ -> accumulator) accumulator

然后,最后一行的调用变成:

countEachNucleobase initialLetterCount dataset

短版

let readChar accumulator = function
    | 'A' -> {accumulator with A = accumulator.A + 1}
    | 'C' -> {accumulator with C = accumulator.C + 1}
    | 'G' -> {accumulator with G = accumulator.G + 1}
    | 'T' -> {accumulator with T = accumulator.T + 1}
    | _ -> accumulator

let countEachNucleobase acc input = Seq.fold readChar acc input

由于字符串是字符序列,input 将接受字符串以及字符数组或其他字符序列。

【讨论】:

  • 感谢 Vandroiy 的回复。当我尝试使用您的 Array.fold 建议时,我收到一条错误消息:“此表达式应具有 char [] 类型,但此处具有 DNANucleobases 类型”
  • @MY_G 这很奇怪。你确定你使用的代码和这里的代码完全一样,countEachNucleobase 和最后一行都被替换了吗?当我以交互方式尝试时,它运行良好。
猜你喜欢
  • 2020-10-17
  • 2011-10-22
  • 2011-03-27
  • 1970-01-01
  • 1970-01-01
  • 2022-12-05
  • 1970-01-01
  • 2011-05-11
  • 1970-01-01
相关资源
最近更新 更多