Haskellで文字列っぽい型同士を結合する演算子+++
が欲しい。左辺、右辺、返り値の関係は下表のようになって欲しい。
左辺 \ 右辺 | String | Lazy.Text | Text | Lazy.ByteString | ByteString |
---|---|---|---|---|---|
String | String | Lazy.Text | Text | Lazy.ByteString | ByteString |
Lazy.Text | Lazy.Text | Text | Lazy.ByteString | ByteString | |
Text | Text | Lazy.ByteString | ByteString | ||
Lazy.ByteString | Lazy.ByteString | ByteString | |||
ByteString | ByteString |
そういう型クラスFlexibleAppendable
を作ってみる
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
module FlexibleAppendable where
import Data.Monoid
import Data.String
import qualified Data.ByteString.Char8 as CB
class (IsString l, IsString r, IsString a) => FlexibleAppendable l r a | l r -> a where
(+++) :: l -> r -> a
instance FlexibleAppendable String String String where
(+++) l r = l ++ r
instance FlexibleAppendable String CB.ByteString CB.ByteString where
(+++) l r = CB.pack l <> r
-- 以下似たようなものがえんえん続く
動かしてみる
s :: String
s = "Hello, "
bs :: CB.ByteString
bs = CB.pack "World !"
main = CB.putStrLn $ s +++ bs
実行結果
Hello, World
きっちり動く。しかし、OverloadedStrings拡張を有効にしていると動かない
{-# LANGUAGE OverloadedStrings #-}
main = CB.putStrLn $ "Hello, " +++ bs
エラーメッセージはこちら
No instance for (IsString l0) arising from the literal ‘"Hello, "’
The type variable ‘l0’ is ambiguous
Note: there are several potential instances:
instance IsString aeson-0.11.2.0:Data.Aeson.Types.Internal.Value
-- Defined in ‘aeson-0.11.2.0:Data.Aeson.Types.Internal’
instance IsString CB.ByteString
-- Defined in ‘Data.ByteString.Internal’
instance IsString Data.ByteString.Lazy.Internal.ByteString
-- Defined in ‘Data.ByteString.Lazy.Internal’
...plus 8 others
In the first argument of ‘(+++)’, namely ‘"Hello, "’
In the second argument of ‘($)’, namely ‘"Hello, " +++ bs’
In the expression: CB.putStrLn $ "Hello, " +++ bs
OverloadedStringsはできれば有効にしておきたいため、これではいまいち。
進展があったら「その2」を投稿します。
進展があったので「その2」を投稿しました→ http://qiita.com/saturday06/items/310721929cacf83fa648