Haskell 为什么不是';这不是打字很好吗?
我正在编写一个函数来生成一组字符串的所有排列--“foo”应该返回{“foo”,“ofo”,“oof”}。我已经在Clojure中这样做了,所以我知道这种方法是正确的,但我想我应该在Haskell中进行实践。下面是我得到的Haskell 为什么不是';这不是打字很好吗?,haskell,Haskell,我正在编写一个函数来生成一组字符串的所有排列--“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 $
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!"
当然,这不是编译,否则我不会问。我得到:
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)
Set.map
声明为(a->b)->Set a->Set b
。据我所知,recurFunc
获取一组(Char,String)
对,并返回一组字符串substrs
返回一组(字符、字符串)
对。那么这是怎么不一致的呢?请注意:键入String=[Char]
Set.map
采用普通函数并将其映射到集合上。由于您有一个集(Char,String)
并且您想要一个集字符串
,因此此函数的类型应为(Char,String)->String
但是,recurFunc
返回的是一个集合,而不仅仅是一个字符串。也就是说,它有一个类型(Char,String)->Set String
。(我认为类型实际上更一般,但这并不重要。)因此,当你将它映射到一个集合上时,你会得到一组集合:类似于set(set String)
这是您的错误以稍微有点偏颇的方式说的:它期望一个Set字符串
,但得到了一个Set(Set字符串)
。但是,由于错误是关于recurFunc
,因此它只告诉您函数的问题:Set String
应该是String
希望这能为您提供足够的信息来修复错误。利用
String
s只是Char
s的列表这一事实,您可以快速编写:
import Data.List
permute = Eq a => [a] -> [[a]]
permute = nub . permutations
预定义的permutations
实际上生成了您想要的所有作业,而nub
只是删除重复项
请注意,这种方法不是非常有效(O(n^2)),应该只用于少量数据 我建议首先使用基于列表的版本,然后调整它,以便在以后如果您决定确实需要它时使用
Set
。列表不那么容易混淆(而且,对于像这样的少量数据,Set
也不会快很多)。