2008-11-14 3 views
3

Эй, я действительно новичок в Haskell, и всю свою жизнь использовал более классические языки программирования. Я понятия не имею, что здесь происходит. Я пытаюсь сделать очень простой алгоритм алгоритма Витерби, но только для двух состояний (честное и нечестное казино)Новое для функционального программирования

У меня проблема, когда я хочу обратиться к массиву, но я не думаю, что получаю типы правильные. Это или я делаю новый массив каждый раз, когда я пытаюсь его решить - в равной степени глупо. Посмотрите на myArray, te infix и dynamicProgram, особенно, ПОЖАЛУЙСТА. Довольно довольно угождать

 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 

ответ

11

Я скопировал код из окна редактирования (что-то в парсер StackOverflow в съедает часть кода) и попробовал его на GHCI, который нашел несколько ошибок. Первая ошибка:

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 

Тип listArray является:

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

Он принимает кортеж с нижними и верхними границами и списком. Таким образом, правильное выражение, вероятно, будет:

listArray (startIndex, endIndex) values 

И тип туАггау не Array a b, это Array Int Double.

Вторая ошибка:

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)) 

$ прав ассоциативно, поэтому крайний правый $ смотрится на первый. Первым параметром для него должна быть функция, которую он будет вызывать с ее самым правым параметром в качестве аргумента. Здесь, однако, это список.

Третья ошибка:

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 не является массивом; это функция, которая принимает три параметра и создает на их основе массив.

Здесь, вероятно, ваше привыкание к более традиционным императивным языкам отключает вас. В традиционном императивном языке было бы естественно иметь глобальную переменную myArray, которую вы можете получить из середины вашей программы. В Haskell, однако, при отсутствии более продвинутой хитрости, которую вы не должны попробовать, пока вы новичок, «глобальная» переменная больше похожа на постоянную ценность (которая лениво вычисляется при первом использовании, но которая, насколько вам может быть, рассчитана компилятором при создании исполняемого файла). Вы не можете инициализировать его из значений, которые вы читаете как входные данные.

Ваш лучший способ - передать массив через программу, которая, к сожалению, потребует нескольких изменений и отрицает полезность вашего оператора @@. Вы можете скрыть передачу массива несколькими более продвинутыми способами, но при обучении лучше всего быть более явным.

Последняя ошибка:

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) 

Это имеет две ошибки: один компилятор жаловался проблема старшинства, как скобка компилятора добавил Readly шоу, и которые могут быть легко исправлены с помощью правильного применения либо скобки, либо оператора $.Другая ошибка, которую вы обнаружите после исправления этого, заключается в том, что вы не можете конкатенировать строку и число; вам нужно преобразовать число в строку.

Это все, не смотря на алгоритм или даже большую часть кода, просто глядя на ошибки компилятора. Если вы хотите двумерный массив, например, правильное выражение для первой ошибки будет:

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

Теперь оба границ являются кортежами, и его типа Array (Int, Int) Double.

+0

Очень красиво сделано! – Godeke 2008-11-15 00:13:35

1

Вы можете переписать транс-функцию, как это:

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