アレイのuniq どう書く?org

Twitter向井さんがこんなこと言っていた。

http://ja.doukaku.org/16/ne... お題が「アレイのuniq」なのに Haskeller が Array ではなくリストを使っている件

http://twitter.com/jmuk/statuses/144327752

というわけで、反応してみる。

import Data.List ( nub ) 
import Array

aryUniq ::( Eq e , Ix i) => Array i e -> Array i e
aryUniq a = listArray ( bounds a ) $ nub $ Array.elems a

で、実行

$ ghci uniq_ary.hs
   ___         ___ _
  / _ \ /\  /\/ __(_)
 / /_\// /_/ / /  | |      GHC Interactive, version 6.6, for Haskell 98.
/ /_\\/ __  / /___| |      http://www.haskell.org/ghc/
\____/\/ /_/\____/|_|      Type :? for help.

Loading package base ... linking ... done.
[1 of 1] Compiling Main             ( uniq_ary.hs, interpreted )

*Main> let a = listArray (0,10) [1,3,4,2,1,3,4,5,6,3,2]
*Main> a
array (0,10) [(0,1),(1,3),(2,4),(3,2),(4,1),(5,3),(6,4),(7,5),(8,6),(9,3),(10,2)]
*Main> aryUniq a
Loading package haskell98 ... linking ... done.
array (0,10) [(0,1),(1,3),(2,4),(3,2),(4,5),(5,6),(6,*** Exception: (Array.!): undefined array element

素数減ったのに、範囲がそのままだから、ダメみたいだ。
なので、範囲もいじる。

import Data.List ( nub )
import Array

aryUniq ::( Eq e , Ix i , Enum i) => Array i e -> Array i e
aryUniq a = listArray ( fstBounds a , sndBounds a ) $ uniqArrayElem a
    where 
          uniqArrayElem :: (Ix i, Eq e) => Array i e -> [e]
          uniqArrayElem a = nub $ Array.elems a
          fstBounds :: (Ix i) => Array i e -> i
          fstBounds  a  = fst $ bounds a
          sndBounds :: (Eq e, Ix i, Enum i) => Array i e -> i
          sndBounds a = sndBounds' (fstBounds a) $ length $ uniqArrayElem a
          sndBounds' :: (Enum a) => a -> Int -> a
          sndBounds' f l = head $ reverse $ take l [f..]

ごちゃごちゃしたうえに、範囲がEnumのみになる最低。でもエラーがでなくなった。

$ ghci uniq_ary.hs
   ___         ___ _
  / _ \ /\  /\/ __(_)
 / /_\// /_/ / /  | |      GHC Interactive, version 6.6, for Haskell 98.
/ /_\\/ __  / /___| |      http://www.haskell.org/ghc/
\____/\/ /_/\____/|_|      Type :? for help.

Loading package base ... linking ... done.
[1 of 1] Compiling Main             ( uniq_ary.hs, interpreted )
Ok, modules loaded: Main.
*Main> let a = listArray (0,10) [1,3,4,2,1,3,4,5,6,3,2]
*Main> aryUniq a
Loading package haskell98 ... linking ... done.
array (0,5) [(0,1),(1,3),(2,4),(3,2),(4,5),(5,6)]

あまり使い慣れていないモジュール使ったりすると、シンプルに書けなくなってしまうなぁ。