函数式编程新手

发布于 2024-07-09 03:30:50 字数 2893 浏览 12 评论 0原文

嘿,我对 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 | 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

Hey, I'm really new to Haskell and have been using more classic programming languages my whole life. I have no idea what is going on here. I'm trying to make a very simple Viterbi algorithm implementation, but for only two states (honest and dishonest casino)

I have a problem where I want to address my array, but I don't think I'm getting types right. That or I'm making a new array each time I try to address it - equally stupid. Look at myArray, te infix, and dynamicProgram especially, PLEASE. Pretty pretty please

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

南笙 2024-07-16 03:30:50

我从编辑窗口复制了代码(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。

I copied the code from the edit window (something in stackoverflow's parser is eating part of the code) and tried it on ghci, which found several errors. The first error was:

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

The type of listArray is:

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

It takes a tuple with the lower and upper bounds and the list. So, the correct expression would probably be:

listArray (startIndex, endIndex) values

And the type of myArray is not Array a b, it is Array Int Double.

The second error was:

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

$ is right associative, so the rightmost $ is looked at first. The first parameter to it must be a function, which it will call with its rightmost parameter as the argument. Here, however, it is a list.

The third error was:

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 is not an array; it is a function which takes three parameters and constructs an array based on them.

Here probably your being used to more traditional imperative languages is tripping you. In a traditional imperative language, it would be natural to have a global myArray variable which you then can access from the middle of your program. In Haskell however, absent more advanced trickery which you should not try while you are a beginner, a "global" variable is more like a constant value (which is lazily computed on first use, but which as far as you care could have been computed by the compiler while generating your executable). You cannot initialize it from values you read as input.

Your best way around that is to pass the array through the program, which unfortunately will need several changes and negates the usefulness of your @@ operator. You can hide the passing of the array in several more advanced ways, but while learning it is best to be more explicit.

The last error was:

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)

This has two errors: the one the compiler complained about is a precedence problem, as the compiler-added parenthesis readly show, and which can easily be fixed by correct application of either parenthesis or the $ operator. The other error, which you will find after you fix this one, is that you cannot concatenate a string and a number; you have to convert the number to a string.

This was all without looking at the algorithm or even most of the code, just looking at the compiler errors. If you want a two-dimensional array, for instance, the correct expression for the first error would be:

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

Now both bounds are tuples, and its type is Array (Int, Int) Double.

挽手叙旧 2024-07-16 03:30:50

您可以像这样重写转换函数:

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

You can rewrite the trans-function like this:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文