2014-02-26 26 views
0

我想创建一个函数,首先将一个列表l分为两个列表m和n。然后创建两个线程来找出两个列表中最长的回文。我的代码是:Haskell:如何在一个do块中操作字符串类型

import Control.Concurrent (forkIO) 
import System.Environment (getArgs) 
import Data.List 
import Data.Ord 

main = do 
    l <- getArgs 
    forkIO $ putStrLn $ show $ longestPalindr $ mList l 
    forkIO $ putStrLn $ show $ longestPalindr $ nList l 

longestPalindr x = 
    snd $ last $ sort $ 
     map (\l -> (length l, l)) $ 
      map head $ group $ sort $ 
       filter (\y -> y == reverse y) $ 
        concatMap inits $ tails x 

mList l = take (length l `div` 2) l 

nList l = drop (length l `div` 2) l 

现在我可以编译它,但结果是[]。当我刚刚运行longestPalindrmList时,我得到了正确的结果。我认为这里的逻辑是正确的。那么问题是什么?

+0

那么我在这里错了什么?@bheklilr – Xie

+0

这对我来说编写得很好。我不认为'longestPalindr'会做你想做的事情。另外,由于不涉及真正的IO,因此考虑使用'par'和'seq'可能更明智,然后让运行时为您平行化,而不是使用'forkIO'。 – thumphries

+0

'longestPalindr'获得一个字符串中最长的回文。但无论如何,我对如何使用'par'与它决斗感兴趣。你能告诉我怎么做吗?@bheklilr – Xie

回答

1

问题标题可能需要更改,因为这不再是关于类型错误。

程序的功能可以通过在列表的两半之间简单地映射longestPalindr来修复。在你的代码中,你找到了[[Char]]之间最长的回文,所以结果长度通常只有1.

我给出了一个简单的例子parpseq。这只是向编译器建议,独立评估左侧和右侧可能很明智。它并不保证并行评估,而是由编译器决定。

请参阅wiki上的Parallel Haskell以了解火花,使用-threaded标志进行编译,然后使用+RTS -N2运行它。添加-stderr进行分析,并查看是否有任何好处引发此处。直到您开始填充更长的列表时,我才会期望得到负面回报。

有关功能并行性的更多信息,请参阅Control.Parallel.Strategies。在非确定性场景中真正需要在Haskell中手动加入线程。

import Control.Parallel (par, pseq) 
import System.Environment (getArgs) 
import Data.List 
import Data.Ord 
import Control.Function (on) 

main = do 
    l <- getArgs 
    let left = map longestPalindr (mList l) 
     right = map longestPalindr (nList l) 
    left `par` right `pseq` print $ longest (left ++ right) 

longestPalindr x = longest pals 
    where pals = nub $ filter (\y -> y == reverse y) substrings 
      substrings = concatMap inits $ tails x 

longest = maximumBy (compare `on` length) 

mList l = take (length l `div` 2) l 

nList l = drop (length l `div` 2) l 
+0

谢谢,我已经尝试只是添加地图到我的代码。 'forkIO $ putStrLn $ show $ map longestPalindr(mList l)',我还有一个[]。我把地图放错了地方? – Xie

+0

我得到了错误的答案,直到我用'maximum'替换了'snd $ last $ sort'。 – thumphries

+0

但我不想得到长度,只想要最长的字符串。所以我需要我的代码中的'snd $ last $ sort'。那么如何与[[Char]]问题决斗呢? – Xie

0

仅供参考,请阅读Simon Marlow书中的Parallel一章。 http://chimera.labs.oreilly.com/books/1230000000929/ch02.html#sec_par-eval-whnf

正如其他人所说的那样,使用Eval中的par monad似乎是正确的方法。 这是您的问题的简化视图。您可以使用+RTS -threaded -RTS进行编译来测试它,然后可以使用Thread Scope来分析您的性能。

import   Control.Parallel.Strategies 
import   Data.List     (maximumBy, subsequences) 
import   Data.Ord 

isPalindrome :: Eq a => [a] -> Bool 
isPalindrome xs = xs == reverse xs 

-- * note while subsequences is correct, it is asymptotically 
-- inefficient due to nested foldr calls 

getLongestPalindrome :: Ord a => [a] -> Int 
getLongestPalindrome = length . maximum' . filter isPalindrome . subsequences 
    where maximum' :: Ord a => [[a]] -> [a] 
     maximum' = maximumBy $ comparing length  

--- Do it in parallel, in a monad 
-- rpar rpar seems to fit your case, according to Simon Marlow's book 
-- http://chimera.labs.oreilly.com/books/1230000000929/ch02.html#sec_par-eval-whnf 
main :: IO() 
main = do 
    let shorter = [2,3,4,5,4,3,2] 
     longer = [1,2,3,4,5,4,3,2,1] 
     result = runEval $ do 
       a <- rpar $ getLongestPalindrome shorter 
       b <- rpar $ getLongestPalindrome longer 
       if a > b -- 'a > b' will always be false in this case 
       then return (a,"shorter") 
       else return (b,"longer") 
    print result 
-- This will print the length of the longest palindrome along w/ the list name 
-- Don't forget to compile w/ -threaded and use ThreadScope to check 
-- performance and evaluation 
+0

非常感谢! – Xie

+0

没问题;)很乐意帮忙。随时接受问题,如果它帮助你。坚持瓦斯/哈斯克尔! –