LoginSignup
4
3

More than 5 years have passed since last update.

Haskellで文字列っぽい型同士を結合する演算子が欲しい。その2(動作するところまでは行った)

Last updated at Posted at 2016-09-14

←前回の記事

前回までのあらすじ

Haskellで文字列っぽい型同士を結合する演算子+++が欲しい。左辺、右辺、返り値の関係は下表のようになって欲しい。また、 foo :: String +++ bar :: ByteString のような型注釈は不要なようにしたい

左辺 \ 右辺 文字列リテラル String Lazy.Text Text Lazy.ByteString ByteString
文字列リテラル String 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を作ってみるが、Haskell力が足らずにコンパイルが通るものが作れなかった。

コンパイルが通って動作するところまで到達したバージョン

  • コメント欄で @hiratara さんという方に {-# OVERRAPPABLE #-} プラグマをおしえてもらったので使ってみた
  • {-# OverloadedStrings #-} な文字列リテラルから中身の文字列を取り出すのに、unsafeCoerce を使ってみた
{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings     #-}
{-# LANGUAGE UndecidableInstances  #-}

import qualified Data.ByteString.Char8 as CB
import           Data.Monoid
import           Data.String
import           Unsafe.Coerce

class FlexibleAppendable l r a where
  (+++) :: l -> r -> a

instance {-# OVERLAPPABLE #-} (IsString l) => FlexibleAppendable l CB.ByteString CB.ByteString where
  (+++) l r = fromString (unsafeCoerce l :: String) <> r

instance {-# OVERLAPPABLE #-} (IsString l, IsString r) => FlexibleAppendable l r String where
  (+++) l r = fromString $ (unsafeCoerce l :: String) <> (unsafeCoerce r :: String)

-- 以下似たようなものがえんえん続く

動かしてみる

main :: IO ()
main = do
  putStrLn $ "Hello, " +++ "World"
  CB.putStrLn $ "Hello, " +++ CB.pack "World"

実行結果

Hello, World
Hello, World

動いた。すごい!

ただ、この実装の場合こちらが想定している型以外の独自のIsStringインスタンスが渡された際にruntime corruptionが発生することがあります。こちらが把握していないデータ構造に対して強制キャストをするためです。Unsafe.Coerceの解説に書いてありました。やばそうなので改善したい機運が凄いです。

進展があったら「その3」を投稿します。進展ありました→ http://qiita.com/saturday06/items/72c98df4e3d1481962b1

4
3
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3