簡體   English   中英

嵌套的塊在Haskell中?

[英]Nested chunksOf in Haskell?

說我想這樣做:

nestedChunksOf [3, 2] [1,1,1,2,2,2,3,3,3,4,4,4] == [[[1,1,1], [2,2,2]], [[3,3,3], [4,4,4]]]

在Python中,我可以做到這一點

def group(a, *ns):
    for n in ns:
        a = [a[i:i+n] for i in xrange(0, len(a), n)]
    return a

group([1,1,1,2,2,2,3,3,3,4,4,4], 3, 2) == [[[1,1,1],[2,2,2]],[[3,3,3],[4,4,4]]]

但在哈斯克爾,我不能只說

nestedChunksOf :: [Int] -> [a] -> [[a]]

要么

nestedChunksOf :: [Int] -> [a] -> [[[a]]]

那么如何才能在Haskell中實現同樣的功能呢?

nestedChunksOf這樣的函數不能直接在Haskell中完成,至少不能在普通列表上運行。 列表的深度是類型的一部分,因此您不能具有參數指定的任意深度。

但你可以做的是嵌套chunksOf

如果我們定義chunksOf如下:

chunksOf :: Int -> [a] -> [[a]]
chunksOf _ [] = []
chunksOf n xs = fxs : chunksOf n sxs
    where (fxs, sxs) = splitAt n xs

我們可以嵌套它:

Main> :l test.hs
[1 of 1] Compiling Main             ( test.hs, interpreted )
Ok, modules loaded: Main.
*Main> chunksOf 3 [1,1,1,2,2,2,3,3,3,4,4,4]
[[1,1,1],[2,2,2],[3,3,3],[4,4,4]]
*Main> chunksOf 2 $ chunksOf 3 [1,1,1,2,2,2,3,3,3,4,4,4]
[[[1,1,1],[2,2,2]],[[3,3,3],[4,4,4]]]

我希望能完成你想要的!

正如其他答案中所述,這不能直接完成,因為在Haskell中你總是需要知道表達式的類型,從而區分[a][[a]]等。但是,使用多態遞歸你可以定義一種數據類型,它允許通過在構造函數中包裝每個級別來進行任意嵌套:

data NestedList a = Value a | Nested (NestedList [a])
  deriving (Show)

因此,只有Valuea同構, Nested (Value ...)[a]同構,雙Nested[[a]]等。然后你可以實現

chunksOf :: Int -> [a] -> [[a]]
...

nestedChunksOf :: [Int] -> [a] -> NestedList a
nestedChunksOf [] xs = Nested (Value xs)
nestedChunksOf (c:cs) xs = Nested (nestedChunksOf cs $ chunksOf c xs)

確實如此

print $ nestedChunksOf [3, 2] [1,1,1,2,2,2,3,3,3,4,4,4]

輸出

Nested (Nested (Nested (Value [[[1,1,1],[2,2,2]],[[3,3,3],[4,4,4]]])))

使用依賴類型可以相當容易地完成。

我們想表示[Int]參數的長度決定了結果的類型。 我們需要兩件事:一個具有固定長度的列表類型,以及一個從長度計算返回類型的類型級函數:

{-# LANGUAGE DataKinds, GADTs, TypeFamilies #-}

import Data.List.Split

data Nat = Z | S Nat -- natural numbers (zero, successor)

data Vec n a where -- "n" length lists of "a" elements
  Nil  :: Vec Z a
  (:>) :: a -> Vec n a -> Vec (S n) a
infixr 5 :>

type family Iterate n f a where
  Iterate Z     f a = a
  Iterate (S n) f a = f (Iterate n f a)

Iterate nfa適用類型構造f n次爭論。 例如, Iterate (S (SZ)) [] Int減少為[[Int]] nestedChunksOf現在可以直接編寫:

nestedChunksOf :: Vec n Int -> [a] -> Iterate (S n) [] a
nestedChunksOf Nil       as = as
nestedChunksOf (n :> ns) as = chunksOf n $ nestedChunksOf ns as

用法:

> nestedChunksOf (2 :> 3 :> Nil) [1,1,1,2,2,2,3,3,3,4,4,4]
[[[1,1,1],[2,2,2]],[[3,3,3],[4,4,4]]]

這在Haskell中無法通過“正常”方式實現,因為它需要依賴類型 - 結果的類型取決於第一個參數的長度。

也許一個元組解決方案是可以接受的?

{-# Language TypeFamilies #-}
{-# Language FlexibleInstances #-}
import Data.List.Split
class NestedChunksOf a where
    nco :: a -> [b] -> AList a b
    type AList a b :: *

instance NestedChunksOf (Int,Int) where
    nco (f,s) xs = chunksOf f (chunksOf s xs)
    type AList (Int,Int) a = [[[a]]]


-- More instances as desired.

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM