我正在编写一个函数来生成一组字符串的所有排列 - "foo"应该返回{"foo","ofo","oof"}.我已经在Clojure中完成了这个,所以我知道这种方法是正确的,但我想我会在Haskell中进行练习.以下就是我所拥有的.
import qualified Data.Set as Set
substr :: String -> Int -> Int -> String
substr s start end = take (end - start) . drop start $ s
substrs :: String -> Set.Set (Char, String)
substrs s = let len = length s
in foldl (\acc x -> Set.insert (s !! x, ((substr s 0 x)++(substr s (succ x) len))) acc) Set.empty [0..len-1]
-- not sure about the type
permute [] = Set.empty
permute s = Set.map recurFunc (substrs s)
where recurFunc (c, s) = Set.map (c:) (permute s)
main :: IO ()
main = print $ permute "foo!"
Run Code Online (Sandbox Code Playgroud)
当然,这不会编译,或者我不会问.我明白了:
permute.hs:12:21:
Couldn't match expected type `String'
with actual type `Set.Set [Char]'
Expected type: (Char, String) -> String
Actual type: (Char, String) -> Set.Set [Char]
In the first argument of `Set.map', namely `recurFunc'
In the expression: Set.map recurFunc (substrs s)
Run Code Online (Sandbox Code Playgroud)
Set.map被宣布为(a -> b) -> Set a -> Set b.据我所知,recurFunc采取一组(Char, String)对,并返回一组字符串.substrs返回一组(Char, String)对.那么这是如何不一致的呢?
快速说明:type String = [Char].
Set.map采用普通函数并将其映射到集合上.由于你有一个Set (Char, String)并且你想要一个Set String,这个函数应该有类型(Char, String) -> String.
但是,您recurFunc返回一个集合而不仅仅是一个字符串.也就是说,它有一种类型(Char, String) -> Set String.(我认为这种类型实际上更为通用,但这并不重要.)因此,当您将它映射到一个集合时,您会获得一组集合:类似于Set (Set String).
这就是你的错误以一种略微倾斜的方式说的:它期望一个Set String但得到一个Set (Set String).但是,由于错误是关于recurFunc,它只告诉你函数的问题:Set String应该只是String.
希望这能为您提供足够的信息来修复您的错误.