「Haskell で Kleene閉包」 という記事を読んだのですが、「単純な再帰を使って初期値の与え方を変えれば、重複なしで「Kleene閉包」を求められるんじゃない」か、と考えて自分なりにコーディングしてみました。
こういった分野を専門的に勉強したことはないので、もしかしたら勘違いをしてるかもしれませんが…。
とりあえず、Wikipedia の例はちゃんと求められるようです。
kleeneStar.hs
kleeneStar :: [[a]] -> [[a]]
kleeneStar xs = [] : loop xs
where loop xs' = xs' ++ loop [y ++ z | y <- xs, z <- xs']
> take 15 $ kleeneStar ["ab", "c"]
["","ab","c","abab","abc","cab","cc","ababab","ababc","abcab","abcc","cabab","cabc","ccab","ccc"]
> take 10 $ kleeneStar [['a'], ['b'], ['c']]
["","a","b","c","aa","ab","ac","ba","bb","bc"]
追記
"iterate" を使用した定義を思いつきました。
kleeneStar2.hs
kleeneStar :: [[a]] -> [[a]]
kleeneStar xs = concat $ iterate (\ys -> [y ++ x | y <- ys, x <- xs]) [[]]