2014-02-26 21 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

沒問題;)很樂意幫忙。隨時接受問題,如果它幫助你。堅持瓦斯/哈斯克爾! –