函数式编程新手
嘿,我对 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我从编辑窗口复制了代码(stackoverflow 的解析器中的某些东西正在吃掉部分代码)并在 ghci 上尝试,发现了几个错误。 第一个错误是:
listArray 的类型是:
它需要一个带有下限和上限的元组以及列表。 因此,正确的表达式可能是:
并且 myArray 的类型不是 Array a b,而是 Array Int Double。
第二个错误是:
$
是右关联的,因此首先查看最右边的$
。 它的第一个参数必须是一个函数,它将以其最右边的参数作为参数来调用该函数。 然而,这里是一个列表。第三个错误是:
myArray
不是数组; 它是一个接受三个参数并根据它们构造一个数组的函数。在这里,您可能习惯了更传统的命令式语言,这可能会让您感到困惑。 在传统的命令式语言中,很自然地有一个全局
myArray
变量,然后您可以从程序中间访问该变量。 然而,在 Haskell 中,缺乏更高级的技巧,当你是初学者时你不应该尝试,“全局”变量更像是一个常量值(在第一次使用时延迟计算,但就你所关心的而言,它可以被计算)由编译器在生成可执行文件时执行)。 您无法从作为输入读取的值对其进行初始化。解决这个问题的最佳方法是通过程序传递数组,不幸的是,这需要进行一些更改并否定
@@
运算符的用处。 您可以通过几种更高级的方式隐藏数组的传递,但在学习时最好更明确。最后一个错误是:
这有两个错误:编译器抱怨的一个是优先级问题,正如编译器添加的括号所示,并且可以通过正确应用括号或 $轻松修复。代码> 运算符。 修复此错误后您会发现另一个错误,即无法连接字符串和数字; 你必须将数字转换为字符串。
这一切都没有查看算法甚至大部分代码,只是查看编译器错误。 例如,如果您想要一个二维数组,第一个错误的正确表达式为:
现在两个边界都是元组,其类型为 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:
The type of listArray is:
It takes a tuple with the lower and upper bounds and the list. So, the correct expression would probably be:
And the type of myArray is not
Array a b
, it isArray Int Double
.The second error was:
$
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:
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:
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:
Now both bounds are tuples, and its type is
Array (Int, Int) Double
.您可以像这样重写转换函数:
You can rewrite the trans-function like this: