Reputation: 107
I'm trying to make a DNA transcription program but I'm having trouble with the way I'm doing it, I'm sure there's an easier way to do this but this was the first thing that came to my head but it's not working the way I want it to.
dnaToRna :: [Char] -> [Char]
dnaToRna [] = []
dnaToRna xs = reverse(transc xs)
where transc = (replaceA . replaceT . replaceC . replaceG)
replaceA = map(\c -> if c == 'A' then 'U' else c)
replaceT = map(\c -> if c == 'T' then 'A' else c)
replaceC = map(\c -> if c == 'C' then 'G' else c)
replaceG = map(\c -> if c == 'G' then 'C' else c)
Here's the output:
*Main> let seq = "AAATGTTAGTACACTAAGG"
*Main> dnaToRna seq
"GGUUUGUGUUGUUUGUUUU"
I figure this is because the transc replaces the A, then checks the whole String and replaces the T, etc etc Any tips? Thanks in advance!
Upvotes: 2
Views: 160
Reputation: 26161
@4castle's answer shows the right direction.
Since OP's problem has been solved i believe it would worth to show how to make it more efficient by using Data.Map
for the look ups. Also by using a foldl
we may skip the reversing job as well.
import qualified Data.Map.Lazy as M
dna2rna :: String -> String
dna2rna = foldl (\r c -> (M.findWithDefault '-' c m) : r) ""
where m = M.fromList $ zip "ATCG" "UAGC"
*Main> dna2rna "AAATGTTAGTACACTAAGG"
"CCUUAGUGUACUAACAUUU"
Upvotes: 0
Reputation: 33486
You should make one function which handles all of the Char -> Char
conversions at once.
dnaToRna :: [Char] -> [Char]
dnaToRna = reverse . map transc
where
transc 'A' = 'U'
transc 'T' = 'A'
transc 'C' = 'G'
transc 'G' = 'C'
transc _ = error "Invalid DNA molecule"
To make this even safer, you could make it return a Maybe [Char]
instead. The lookup
function can also be used instead of using a custom mapping function.
dnaToRna :: [Char] -> Maybe [Char]
dnaToRna = mapM (`lookup` zip "ATCG" "UAGC") . reverse
Upvotes: 3