LoginSignup
0

More than 5 years have passed since last update.

Haskellで手軽に変数を文字列に埋め込む - 変数展開

Last updated at Posted at 2017-12-16

やりたいこと

変数の値を文字列に埋め込みたい!

Haskellで、以下みたいに++を使って連結するのは、読みづらいし変更しづらいし嫌ですよね。

let name = "Jack"
    age  = 10
putStrLn ("Name is " ++ name ++ ". His age is " ++ show age ++ ".")

一方、他の言語では、変数を文字列に埋め込む技術が整っています。

Rubyでは、

hello.rb
name = "Jack"
age  = 23
puts("Name is #{name}. His age is #{age}")

JavaScript(ES6?)では、

hello.js
const name = "Jack"
const age  = 23
console.log(`Name is ${name}. His age is ${age}`)

Swiftでは、

hello.swift
let name = "Jack"
let age  = 23
print("Name is \(name). His age is \(age)")

Scalaでは、

hello.scala
val name = "Jack"
val age  = 23
println(s"Name is ${name}. His age is ${age}")

PHPでは、

hello.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

参考

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
0