3

リスト (または文字列) を取り、それを N 個の要素のサブリストに分割したいと考えています。Haskell でどのように行うのですか?

例:

mysteryFunction 2 "abcdefgh"
["ab", "cd", "ef", "gh"]
4

7 に答える 7

13
cabal update
cabal install split

そして、から使用chunksOfしますData.List.Split

于 2013-08-25T08:55:55.153 に答える
1
import Data.List 
import Data.Function

mysteryFunction n = map (map snd) . groupBy ((==) `on` fst) . zip ([0..] >>= replicate n)

... 冗談だ...

于 2013-08-25T13:42:43.543 に答える
1

すでにあります

Prelude Data.List> :t either
either :: (a -> c) -> (b -> c) -> Either a b -> c

Prelude Data.List> :t maybe
maybe :: b -> (a -> b) -> Maybe a -> b

だから本当にあるはずです

list :: t -> ([a] -> t) -> [a] -> t
list n _ [] = n
list _ c xs = c xs

同じように。それと、

import Data.List (unfoldr)

g n = unfoldr $ list Nothing (Just . splitAt n)

それなしで、

g n = takeWhile (not.null) . unfoldr (Just . splitAt n)
于 2013-08-25T17:07:17.173 に答える
1
mysteryFunction x "" = []
mysteryFunction x s = take x s : mysteryFunction x (drop x s)

おそらく、あなたが考えていたエレガントなソリューションではありません。

于 2013-08-25T16:47:56.857 に答える
1

ファンシーな答え。

上記の回答では、再帰的な splitAt も使用する必要があります。再帰的なソリューションをゼロから構築する方法を見てみましょう。

Functor L(X)=1+A*X は、X を 1 にマップするか、A と X のペアに分割することができ、最小固定点として List(A) を持ちます。List(A) は 1+ にマップできます。 A*List(A) と同型を使用して戻る; つまり、空でないリストを分解する方法は 1 つしかなく、空のリストを表す方法は 1 つしかありません。

Functor F(X)=List(A)+A*X は似ていますが、リストの末尾は空のリスト ("1") ではなくなり、ファンクターは値 A を抽出したり、X をリストに変換したりできます。 Asの。その場合、List(A) はその不動点 (ただし、最小固定点ではなくなります) であり、ファンクターは任意のリストをリストとして、または要素とリストのペアとして表すことができます。事実上、任意のコールジェブラは、リストの分解を「自由に」「停止」できます。

{-# LANGUAGE DeriveFunctor #-}
import Data.Functor.Foldable

data N a x = Z [a] | S a x deriving (Functor)

(これは、次の簡単なインスタンスを追加するのと同じです):

instance Functor (N a) where
  fmap f (Z xs) = Z xs
  fmap f (S x y) = S x $ f y

ハイロモルフィズムの定義を考えてみましょう:

hylo :: (f b -> b) -> (c -> f c) -> c -> b
hylo psi phi = psi . fmap (hylo psi phi) . phi

シード値を指定すると、phi を使用して fc を生成し、fmap は hylo psi phi を再帰的に適用し、psi は fmap された構造体 f b から b を抽出します。

このファンクターの (コ) 代数のペアのハイロモーフィズムは、splitAt です。

splitAt :: Int -> [a] -> ([a],[a])
splitAt n xs = hylo psi phi (n, xs) where
  phi (n, []) = Z []
  phi (0, xs) = Z xs
  phi (n, (x:xs)) = S x (n-1, xs)

このコールジェブラは、抽出する頭部があり、抽出された要素のカウンターがゼロでない限り、頭部を抽出します。これは、ファンクターがどのように定義されたかによるものです。phi が S xy を生成する限り、hylo は y を次のシードとして phi に供給します。Z xs が生成されると、ファンクターは hylo psi phi をそれに適用しなくなり、再帰は停止します。

同時に、hylo は構造をリストのペアに再マッピングします。

  psi (Z ys) = ([], ys)
  psi (S h (t, b)) = (h:t, b)

これで、splitAt がどのように機能するかがわかりました。アポモーフィズムを使用して、それを splitList に拡張できます。

splitList :: Int -> [a] -> [[a]]
splitList n xs = apo (hylo psi phi) (n, xs) where
  phi (n, []) = Z []
  phi (0, xs) = Z xs
  phi (n, (x:xs)) = S x (n-1, xs)

  psi (Z []) = Cons [] $ Left []
  psi (Z ys) = Cons [] $ Right (n, ys)
  psi (S h (Cons t b)) = Cons (h:t) b

今回は、再マッピングはアポモルフィズムで使用するように適合されています。右である限り、アポモルフィズムは hylo psi phi を使用してリストの次の要素を生成し続けます。Left の場合は、リストの残りを 1 ステップで生成します (この場合は、[] でリストを終了するだけです)。

于 2013-08-27T09:45:20.733 に答える