2014-03-26 70 views
0

我正在嘗試編寫我自己的函數,它接受任意數量的標記,然後將任意一個字符串分開。Haskell映射與參數更改類型?

經過一番思考之後,我相信我需要遞歸遍歷一個標記列表,然後將每個分割列表傳遞給具有分割函數的貼圖,然後將其展平。

目前,我的算法看起來像這樣:

module MyAwesomeModule where 

import qualified Data.Text as T 

outputSplit :: String -> [String] -> IO() 
outputSplit s tokens = print $ splitRecursive tokens s 

splitRecursive :: [String] -> String -> [String] 
splitRecursive tokens s = splitOneOf tokens s 

splitOneOf :: [String] -> String -> [String] 
splitOneOf [] s = [] 
splitOneOf (t:tokens) s = map (splitOneOf tokens)(map (T.unpack) (T.splitOn (T.pack t) (T.pack s))) ++ (splitOneOf tokens s) 

與錯誤了:

Couldn't match type `[Char]' with `Char' 
Expected type: String -> String 
    Actual type: String -> [String] 
In the return type of a call of `splitOneOf' 
In the first argument of `map', namely `(splitOneOf tokens)' 
In the first argument of `(++)', namely 
    `map 
    (splitOneOf tokens) 
    (map (T.unpack) (T.splitOn (T.pack t) (T.pack s)))' 

所以,據我瞭解,這是什麼意思的是,String S IN初始分割被轉換爲[Char]

Prelude > let a = (map (T.unpack) (T.splitOn (T.pack "a") (T.pack "abcdefabc"))) 
      ["","bcdef","bc"] 
      :t a 
      a::[String] 
      let b = head a 
      :t b 
      b::String 

此外,如果splitOneOf被定義爲:

splitOneOf :: [String] -> String -> [String] 
    splitOneOf [] s = [] 
    splitOneOf (t:tokens) s = (map (T.unpack) (T.splitOn (T.pack t) (T.pack s))) ++ (splitOneOf tokens s) 

然後

Prelude > let a = splitOneOf ["a", "b"] "abcdefghij" 
      ["", "bcdefghij"] 
      map (splitOneOf ["b"]) a 
      [[""], [[""],["cdefghij"]] 

到底是一個什麼在這裏的類型簽名?這是映射的正確方法嗎?我錯過了什麼?

+1

爲什麼地圖有三個參數?你的意思是把'splitOneOf tokens'放入禁忌中嗎? – Emil

+0

感謝您指出,我已經相應地修改了這個問題 –

+0

沒有必要使用Data.Text。有Data.List.Split。 –

回答

1
import Control.Monad ((>=>)) 
import Data.List.Split (splitOn) 

--|Using list monad, for repeated concatMaps 
splitOnMany :: [String] --^delimiters 
      -> String --^input 
      -> [String] --^output 
splitOnMany [] = return 
splitOnMany (d:ds) = splitOn d >=> splitOnMany ds 

該列表單子通常被認爲是某種窮人的非確定性或邏輯單子。但是,無論何時您需要對列表進行遞歸展平,都可以使用它。在這裏,我們分割第一個分隔符,然後分割所有第二個分隔符,等等,然後將所有東西弄平。我很確定明確的遞歸也不是真的有必要。以下是更通用的,甚至可能更好地優化:

import Control.Monad ((>=>)) 
import Data.List.Split (splitOn) 

splitOnMany :: Eq a => [[a]] -> [a] -> [[a]] 
splitOnMany = foldr (>=>) return . map splitOn 
+0

我認爲列表單子monad只會遮蓋這裏的問題,它實際上只是'splitonMany令牌行= foldr(concatMap。splitOn)[行]令牌'。 –

+0

對於你的,爲什麼不foldl'?對我而言,額外的嚴格規定並沒有幫助。我認爲我的內線更好,因爲它沒有任何問題。你說得對,Kleisli魚可能不是太澄清;也許我最近剛剛想到monad。 –