3

嘿,我真的是 Haskell 的新手,我一生都在使用更经典的编程语言。我不知道这里发生了什么。我正在尝试制作一个非常简单的维特比算法实现,但仅适用于两种状态(诚实和不诚实的赌场)

我有一个问题,我想解决我的数组,但我不认为我得到了正确的类型。或者我每次尝试解决它时都会创建一个新数组 - 同样愚蠢。请特别查看 myArray、te 中缀和 dynamicProgram。请漂亮漂亮

代码


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 | x@@y == (1 @@ y-1)*(em (s!!y) em1)*(trans 1 x t1 t2) = '1' : traceback s 1 (y-1) em1 em2 t1 t2
                            | x@@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 (1@@end) (2@@end) == 1@@end = 1
      | maximum (1@@end) (2@@end) == 2@@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
4

2 回答 2

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

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

这有两个错误:编译器抱怨的一个是优先级问题,正如编译器添加的括号很容易显示的那样,并且可以通过正确应用括号或$运算符来轻松修复。修复此错误后您会发现另一个错误是您无法连接字符串和数字;您必须将数字转换为字符串。

这一切都没有查看算法甚至大部分代码,只查看编译器错误。例如,如果你想要一个二维数组,第一个错误的正确表达式是:

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

现在两个边界都是元组,它的类型是Array (Int, Int) Double.

于 2008-11-15T00:11:13.153 回答
1

您可以像这样重写 trans 函数:

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
于 2008-11-26T16:03:05.227 回答