细微的类型错误

时间:2015-03-19 11:24:07

标签: types f#

我是编程新手,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:类型不匹配。   期待一个       DNAN-核碱基 - > string - > DNAN核碱基但给出了一个       DNAN-核碱基 - > string - > DNANucleobases []类型'DNANucleobases'与'DNANucleobases []'类型不匹配

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

1 个答案:

答案 0 :(得分:3)

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

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