2008-11-14 62 views
3

嗨,我真的是Haskell的新手,并且一生都在使用更经典的编程语言。我不知道这里发生了什么。我试图做一个非常简单的Viterbi算法实现,但只有两个州(诚实和不诚实的赌场)函数式编程新手

我有一个问题,我想解决我的数组,但我不认为我得到类型正确。每当我尝试解决它时,我或者正在创建一个新阵列 - 同样愚蠢。尤其要注意myArray,teix和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

我从编辑窗口中复制的代码(东西计算器的解析器吃的部分代码),并试图在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 

而且myArray的类型是不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