やりたいこと
変数の値を文字列に埋め込みたい!
Haskellで、以下みたいに++
を使って連結するのは、読みづらいし変更しづらいし嫌ですよね。
let name = "Jack"
age = 10
putStrLn ("Name is " ++ name ++ ". His age is " ++ show age ++ ".")
一方、他の言語では、変数を文字列に埋め込む技術が整っています。
Rubyでは、
name = "Jack"
age = 23
puts("Name is #{name}. His age is #{age}")
JavaScript(ES6?)では、
const name = "Jack"
const age = 23
console.log(`Name is ${name}. His age is ${age}`)
Swiftでは、
let name = "Jack"
let age = 23
print("Name is \(name). His age is \(age)")
Scalaでは、
val name = "Jack"
val age = 23
println(s"Name is ${name}. His age is ${age}")
PHPでは、
<?php
$name = "Jack";
$age = 23;
print "Name is $name. His age is $age\n";
?>
Haskellでもこれら言語と同じ手軽さで変数を埋め込めるライブラリをみつけたので紹介です
やりかた
interpolateというライブラリを使います。
このライブラリはHaskellのdoctestの作者さんのSimon Hengelさん製のライブラリのようです。
使い方は簡単でQuasiQuotes
言語拡張を有効にして、import Data.String.Interpolate
すれはOKです。
{-# LANGUAGE QuasiQuotes #-}
import Data.String.Interpolate
main :: IO ()
main = do
let name = "Jack"
age = 23
putStrLn [i| Name is #{name}. His age is #{age}.|]
Name is Jack. His age is 23.
[i | ... |]
の中に文字列や変数名を書いていけば展開できます。
#{}
の中には変数名だけではなく、式を書くことができます。
欠点
TemplateHaskell
を使っているのでSafe
なHaskellにならないことが、ちょっと欠点な気がします。
変数を埋め込むだけでSafe
でなくなるのはちょっと痛い気がします...
かといって++
使うのは読みづらく、Text.Printf
使うとフォーマット指定子が足りなかったり、フォーマットの型の間違いで、実行時エラーでるもの嫌ですよね...
とても便利なので個人的にはSafe
にならなくてもinterpolateを使いたいです。何かいい方法ないですかね〜
練習用リポジトリ
以下が実際に使ってみた練習用リポジトリです。
nwtgck/interpolate-prac-haskell