Я пишу функцию для создания набора всех перестановок строки - «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!"
Это не скомпилируется, конечно, или я не прошу. Я получаю:
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
возвращает набор из (Char, String)
пар. Итак, как это противоречиво?
Сначала я предлагаю начать с использованием версии на основе списка, а затем настроить его, чтобы позднее использовать 'Set', если вы решите, что вам действительно нужно. Списки менее запутаны (и, во всяком случае, 'Set' не намного быстрее для небольших объемов данных, подобных этому). –