2015-03-19 62 views
1

我是編程新手,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 []'

出了什麼問題?我應該做什麼改變來糾正我的錯誤?

+0

我認爲你的'Array.map'應該是'array.iter',你需要返回累加器 – 2015-03-19 11:37:57

+0

你必須''摺疊'dnaCharArray'數組,因爲'countEachNucleobase'需要'DNANucleobases'的累加值,不是一個數組。 – 2015-03-19 12:03:19

回答

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 

由於字符串是字符序列,因此input將採用字符串以及字符數組或其他字符序列。

+0

感謝Vandroiy的回覆。當我試圖用你的Array.fold的建議,我得到一個錯誤消息說: 「這個表達,預計將有 類型char [] 但這裏有類型 DNANucleobases」 – 2015-03-19 15:02:22

+0

@MY_G這很奇怪。你確定你正在使用這個代碼嗎?'countEachNucleobase'和最後一行被替換了嗎?當我在互動中嘗試它時,它運行良好。 – Vandroiy 2015-03-19 17:36:12

+0

Vandroiy,它現在有效。謝謝你的幫助。 :-) – 2015-03-20 09:17:05