有没有办法在Haskell中获得“拆分”功能来接受两种不同类型的输入?

我正在尝试创建一个函数拆分,该拆分可以采用[Int]和Int [Char] Char来拆分给定整数上的整数列表或拆分​​字符上的字符串给定的。即

Main> split [1,2,3,4,5,7,8,9] 0
[[1,3],[4,5],[7,9]]
Main> split "Mary had a little lamb" ' '
["Mary","had","a","little","lamb"]

我尝试使用Either和(Eq a),但它似乎仍然不起作用。以下是我尝试使用类实例进行的操作,但对此我知之甚少,并收到错误Haskell 98 does not support multiple parameter classes。 我认为我理解的最好方法是使用模式匹配或列表理解。任何帮助表示赞赏。

class Split a where
  split :: (Eq a) => [a] -> a -> [a]

instance Split [Char] Char where
  split [] c     = [""]
  split (x:xs) c
    | x == c    = "" : (split xs c)
    | otherwise = (x : head (split xs c)) : tail (split xs c)

instance Split [Int] Int where
  split [] n = []
  split (x:xs) n
    | x == n = [] : (split xs n)
    | otherwise = (x : head (split xs n)) : tail (split xs n)

我可以使用split函数来处理字符串和字符,但不能处理整数列表。

liuben1205 回答:有没有办法在Haskell中获得“拆分”功能来接受两种不同类型的输入?

您需要一个多态函数split

split :: (Eq a) => [a]->a->[[a]]

实施很简单

split [] _    = [[]]
split (x:xs) c
  | x == c    = [] : (split xs c)
  | otherwise = (x : head subSplit) : tail subSplit
        where
           subSplit = split xs c

编辑 我建议采用其他实施方式。

split :: Eq a => [a] -> a -> [[a]]
split x c = map reverse $ split' x c []
   where
      split' :: Eq a => [a] -> a -> [a] -> [[a]]
      split' [] _ a = [a]
      split' (x:xs) c a 
         | x == c    = a : split' xs c []
         | otherwise = split' xs c (x:a)
,

只需用其他方法做出贡献即可。此解决方案使用foldr。我认为它很整洁,但不如@talex的

split :: (Eq a) => [a] -> a -> [[a]]
split l c = foldr f acc l
   where acc = [[]]
         f a t@(i@(x:_):xs) = if a == c then []:t else (a:i):xs -- Case when the current accumulator is not empty
--                                           |          |- cons a to current accumulator
--                                           |- start a new accumulator
         f a t@([]:xs)      = if a == c then t    else [a]:xs -- Case when the current accumulator is empty. Usefull when two separators are together
--                                           |          |- cons a to current accumulator
--                                           |- Don't start a new accumulator,just continue with the current
,

只是正确的解决方案。

split :: Eq a => [a] -> a -> [[a]]                                          
split xs delim = go $ dropWhile (== delim) xs                               
  where                                                                     
    go [] = []                                                              
    go xs = let (tok,rest) = break (== delim) xs                           
             in tok : go (dropWhile (== delim) rest)
,

Data.List.Split.splitOn(可从split包中购买)已关闭:

> splitOn [0] [1,2,3,4,5,7,8,9]
[[1,3],[4,5],[],[7,9]]
> splitOn " " "Mary had a little lamb"
["Mary","had","a","little","lamb"]

您的split :: Eq a => [a] -> a -> [[a]]

split lst d = filter (not.null) $ splitOn [d] lst
本文链接:https://www.f2er.com/2942960.html

大家都在问