2008-11-14 13 views
3

Hé, je suis vraiment nouveau à Haskell et j'ai utilisé des langages de programmation plus classiques toute ma vie. Je n'ai aucune idée de ce qui se passe ici. J'essaie de faire une implémentation très simple de l'algorithme de Viterbi, mais pour seulement deux états (casino honnête et malhonnête)Nouveau en programmation fonctionnelle

J'ai un problème où je veux adresser mon tableau, mais je ne pense pas que je reçois types bien. Cela ou je fais un nouveau tableau chaque fois que j'essaye de l'aborder - tout aussi stupide. Regardez myArray, te infix, et dynamicProgram en particulier, S'IL VOUS PLAÎT. Assez joli plaisir

 Code 


import Array 
import Char 

trans :: Int -> Int -> Double -> Double -> Double 
trans from x trans11 trans21 = 
    if (from == 1) && (x == 1) 
     then trans11 
    else if (from == 1) && (x == 2) 
     then (1-trans11) 
    else if (from == 2) && (x == 1) 
     then trans21 
    else (1-trans21) 

em :: Char -> [Double] -> Double 
em c list = list!! a 
    where a = digitToInt c 

intToChar :: Int -> Char 
intToChar n | n == 1 = '1' 
      | n == 2 = '2' 

casino :: Char -> Int -> Int -> [Double] -> [Double] -> Double -> Double -> Double 
casino seqchar 1 y em1 em2 t1 t2= 0.5 * (em seqchar em1) 
casino seqchar 2 y em1 em2 t1 t2= 0.5 * (em seqchar em2) 
casino seqchar x y em1 em2 t1 t2= maximum[ (1 @@ y-1)*(em seqchar em1)*(trans 1 x t1 t2),(2 @@ y-1)*(em seqchar em2)*(trans 2 x t1 t2) ] 

dynamicProgram :: [Char] -> (Char -> Int -> Int -> [Double] -> [Double] -> Double -> Double -> Double) -> [Double] -> [Double] -> Double -> Double -> (Array a b) 
dynamicProgram string score list1 list2 trans11 trans21 = myArray 1 len 
           [score (string!!y) x y list1 list2 trans11 trans21 | x Int -> [Double] -> Array a b 
myArray startIndex endIndex values = listArray (startIndex,startIndex) (endIndex,endIndex) values 

traceback :: [Char] -> Int -> Int -> [Double] -> [Double] -> Double -> Double -> [Char] 
traceback s 1 0 em1 em2 t1 t2 = [] 
traceback s 2 0 em1 em2 t1 t2 = [] 
traceback s x y em1 em2 t1 t2 | [email protected]@y == (1 @@ y-1)*(em (s!!y) em1)*(trans 1 x t1 t2) = '1' : traceback s 1 (y-1) em1 em2 t1 t2 
          | [email protected]@y == (2 @@ y-1)*(em (s!!y) em1)*(trans 2 x t1 t2) = '2' : traceback s 2 (y-1) em1 em2 t1 t2 

answer :: [Char] -> [Double] -> [Double] -> Double -> Double -> [Char] 
answer string list1 list2 t1 t2 = reverse $ maxC : traceback string max end list1 list2 t1 t2 $ dynamicProgram casino string list1 list2 t1 t2 
    where 
     end = (length string) + 1 
     max | maximum ([email protected]@end) ([email protected]@end) == [email protected]@end = 1 
     | maximum ([email protected]@end) ([email protected]@end) == [email protected]@end = 2 
     maxC = intToChar max 

infix 5 @@ 
(@@) i j = myArray ! (i, j) 

main = do 
    putStrLn "What is the sequence to test?" 
    seq state 1 transmission probability?" 
    trp1 state 2 transmission probability is " ++ (1-trp1) 
    putStrLn "What is the state 2 -> state 1 transmission probability?" 
    trp2 state 2 transmission probability is " ++ (1-trp2) 
    putStrLn "I assume that the prob of starting in either state is 1/2. Go!" 
    answer seq st1 st2 trp1 trp2 

Répondre

11

J'ai copié le code de la fenêtre d'édition (quelque chose dans l'analyseur de stackoverflow est de manger une partie du code) et essayé sur ghci, qui a trouvé plusieurs erreurs. La première erreur était:

foo.hs:34:71: 
    Couldn't match expected type `[e]' against inferred type `(a, b)' 
    In the second argument of `listArray', namely 
     `(endIndex, endIndex)' 
    In the expression: 
     listArray (startIndex, startIndex) (endIndex, endIndex) values 
    In the definition of `myArray': 
     myArray startIndex endIndex values 
        = listArray (startIndex, startIndex) (endIndex, endIndex) values 

Le type de ListArray est:

listArray :: (Ix i) => (i, i) -> [e] -> Array i e 
     -- Defined in GHC.Arr 

Il prend un tuple avec les bornes inférieures et supérieures et la liste. Ainsi, l'expression correcte serait probablement:

listArray (startIndex, endIndex) values 

Et le type de monTableau n'est pas Array a b, il est Array Int Double.

La deuxième erreur était:

foo.hs:43:44: 
    Couldn't match expected type `a -> b' 
      against inferred type `[Char]' 
    In the first argument of `($)', namely 
     `maxC : (traceback string max end list1 list2 t1 t2)' 
    In the second argument of `($)', namely 
     `(maxC : (traceback string max end list1 list2 t1 t2)) 
     $ (dynamicProgram casino string list1 list2 t1 t2)' 
    In the expression: 
      reverse 
     $ ((maxC : (traceback string max end list1 list2 t1 t2)) 
     $ (dynamicProgram casino string list1 list2 t1 t2)) 

$ est associative droite, de sorte que le plus à droite $ est regardé d'abord. Le premier paramètre doit être une fonction, appelée avec son paramètre le plus à droite comme argument. Ici, cependant, c'est une liste.

La troisième erreur était:

foo.hs:51:11: 
    Couldn't match expected type `Array i e' 
      against inferred type `Int -> Int -> [Double] -> Array a b' 
    In the first argument of `(!)', namely `myArray' 
    In the expression: myArray ! (i, j) 
    In the definition of `@@': @@ i j = myArray ! (i, j) 

myArray est pas un réseau; c'est une fonction qui prend trois paramètres et construit un tableau basé sur eux.

Ici, vous êtes probablement habitué à des langues impératives plus traditionnelles. Dans un langage impératif traditionnel, il serait naturel d'avoir une variable globale myArray à laquelle vous pouvez accéder depuis le milieu de votre programme. Dans Haskell cependant, en l'absence de trucage plus avancé que vous ne devriez pas essayer quand vous êtes débutant, une variable "globale" ressemble plus à une valeur constante (qui est paresseusement calculée lors de la première utilisation, mais qui aurait pu être calculée par le compilateur lors de la génération de votre exécutable). Vous ne pouvez pas l'initialiser à partir des valeurs que vous lisez en entrée.

Votre meilleur moyen de contourner cela est de faire passer le tableau dans le programme, ce qui nécessitera malheureusement plusieurs changements et annulera l'utilité de votre opérateur @@. Vous pouvez masquer le passage du tableau de plusieurs façons plus avancées, mais tout en apprenant, il est préférable d'être plus explicite.

La dernière erreur était:

foo.hs:63:4: 
    Couldn't match expected type `[a]' against inferred type `IO()' 
    In the first argument of `(++)', namely 
     `putStrLn 
      "I assume that the state 1 -> state 2 transmission probability is "' 
    In the expression: 
      (putStrLn 
      "I assume that the state 1 -> state 2 transmission probability is ") 
     ++ 
      (1 - trp1) 
    In a 'do' expression: 
      (putStrLn 
      "I assume that the state 1 -> state 2 transmission probability is ") 
     ++ 
      (1 - trp1) 

Cela a deux erreurs: celui que le compilateur se plaint est d'un problème de priorité, comme la parenthèse ajouté le compilateur readly show, et qui peut facilement être résolu par l'application correcte de l'une des parenthèses ou de l'opérateur .L'autre erreur, que vous trouverez après avoir corrigé celui-ci, est que vous ne pouvez pas concaténer une chaîne et un nombre; vous devez convertir le nombre en une chaîne. Tout cela sans regarder l'algorithme ou même la majeure partie du code, juste en regardant les erreurs du compilateur. Si vous voulez un tableau à deux dimensions, par exemple, l'expression correcte pour la première erreur serait:

listArray ((startIndex, startIndex), (endIndex, endIndex)) values 

Maintenant, les deux bornes sont tuples, et son type est Array (Int, Int) Double.

+0

Très bien fait! – Godeke

1

Vous pouvez réécrire la trans-fonction comme ceci:

trans :: Int -> Int -> Double -> Double -> Double 
trans 1 1 trans11 trans21 = trans11 
trans 1 2 trans11 trans21 = 1-trans11 
trans 2 1 trans11 trans21 = trans21 
trans _ _ trans11 trans21 = 1-trans21