型クラス

Preludeの関数と、ByteStringの関数は、名前と機能が重複してるものが大量にあるのだけど、普通に両方使おうとすると

Prelude> :m + Data.ByteString
Prelude Data.ByteString> :t length

<interactive>:1:0:
    Ambiguous occurrence `length'
    It could refer to either `length', imported from Prelude
                          or `length', imported from Data.ByteString
Prelude Data.ByteString> :t Data.ByteString.length
Data.ByteString.length :: ByteString -> Int
Prelude Data.ByteString> :t Prelude.length
Prelude.length :: [a] -> Int

とかなってうざい件。

This module is intended to be imported qualified, to avoid name clashes with Prelude functions. eg.

 import qualified Data.ByteString as B

と書いてあるけど、両者のアルゴリズムはしばしば共通して使えるんでないのかな〜という気がするので(例えば、あまり意味はないけど、getContents>>=putStrとか)、B.lengthとlengthを区別せずに済む方法があればいいのにと思う。


で、型クラス使えばいいような気がして

{-# OPTIONS -fglasgow-exts #-}
module Container where
import Data.Word
import qualified Data.ByteString  as S
import Data.ByteString hiding  (length,map,null)
import qualified Prelude as P
import Prelude hiding          (length,map,null)

class Container s a where
 length :: s -> Int
 map :: (a -> a) -> s -> s

instance Container [t] t where
 length = P.length
 map = P.map

instance Container ByteString Word8 where
 length = S.length
 map = S.map

とか書いてみたんだけど

*Container> length [1,2,3]

<interactive>:1:0:
    No instance for (Container [t] a)
      arising from use of `length' at <interactive>:1:0-13
    Possible fix: add an instance declaration for (Container [t] a)
    In the expression: length [1, 2, 3]
    In the definition of `it': it = length [1, 2, 3]

しょぼーん(´・ω・`)こういうの何とかなんないかな〜。後付けで、こういう拡張をしたいという状況はしばしばあると思うんだけど

どーでもいいけど、型クラスって普段あんまり自分で型クラス定義したりしないような。それとも、みんなバリバリ定義してるんだろうか。