0
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

updated at

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

やりたいこと

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

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

参考

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
0
Help us understand the problem. What are the problem?