Why doesn’t Haskell have a ‘format’ function for string interpolation?

I’m trying to use Shake and I stumbled upon the following problem: there’s no easy and convenient way to interpolate a string. I know about Text.Printf — it’s not what I’m looking for. The interpolation syntax I’m talking about is like this:

(Make)

HEADERS_DIR := /some/path/to/dir

CFLAGS := "-g -I$(HEADERS_DIR) -O2"

(Python)

headers_dir = "/some/path/to/dir"

cflags = "-g -I{headers_dir} -O2".format(**locals())

And now compare this to possible Haskell’s solution. Firstly:

$ cabal install interpolatedstring-perl6
$ ghci -XExtendedDefaultRules -XQuasiQuotes

And then:

> import Text.InterpolatedString.Perl6 (qq)
> let headers_dir = "/path/to/some/dir"
> [qq| -g -I$headers_dir -O2 |] :: String

While I think Make goes maybe a step too far in its eagerness to interpolate even when not asked, I wonder why Haskell doesn’t have a format function like Python does. It could parse the supplied string and pull the value with same name as referenced in pattern:

let headers_dir = "/path/to/some/dir"
format "-g -I$headers_dir -O2"

Is there a specific reason why it’s not implemented, or everyone is just happy with Text.Printf‘s verbosity and/or lengthy setup of interpolation libraries?

Update: A lot of people misinterpret the question as asking about general string formatting, with possibility of precision specification in case of integers, etc. The examples provided demonstrate one specific case of interpolation, which is just “substitute the result of show a at the place of name”. It does allow for simpler syntax, and it does not use a variadic function per se.

9

I suspect it’s done as quasiquoting because this will interpolate the string at compile time, and due to the pure nature of functions in Haskell this is possible while other languages lack such ability because of their impure nature.

Think about it, other languages have to do it during runtime each time which is going to be much slower than the compile time once and done quasi-quoted interpolation.

If you want to do it at runtime explicitly then you should be able to do some simple abstractions that take advantage of Haskell’s strings being lists, or you could create a different data structure that’s similar pretty easily – but I would go for the more efficient quasi-quoted approach if I were doing this in any code I actually cared about.

That said, I found on Hackage the Data.Text.Format package which appears to do C# style substitution pretty straight forward, here’s an answer showing an example on SO:
String formatting in Haskell – though as noted by Bryan O’Sullivan and others on that question that answer usess an out-dated package and there’s a newer one Bryan has created (my guess the Data.Text.Format package is his new one that should be used) so the usage may be slightly different from in that SO example, though appears fairly similar.

4

The best typesafe approach I can offer you is the formatting library

{-# LANGUAGE OverloadedStrings #-}

import Formatting (format, (%))
import Formatting.ShortFormatters (t) 

headers_dir = "/path/to/some/dir"

example = format ("-g -I" % t % " -O2") headers_dir

GHCi> example 
"-g -I/path/to/some/dir -O2"

1

updated after question update

I feel that the python version:

"-g -I{headers_dir} -O2".format(**locals())

is an abuse of the language. So I wouldn’t say that python really offers local variable interpolation in strings. In fact, few languages have it.

Answering why language X doesn't have feature Y often comes down to saying that the designers did not feel that it was worth it. In the case of local variable interpolation in strings, it is very much a niche thing used in languages focused on command line scripts. Which Haskell is not. The fact that you can do it in python only comes from the (too?) powerful reflection facilities of the language.

Now why is Text.InterpolatedString.Perl6 so complex to use? It relies on quasiquotations, which is not part of the haskell language. It is a ghc language extension, so you have to declare its usage somewhere. If you exclude the library installation & the language extension declaration, its usage is not really more complex than in your other examples, and is more safe.

3

In Python: the language actually specifies that variables can be referenced by name at runtime. In Haskell: names for everything except top level bindings tend to get erased during compile time and replaced with numeric references.

In your example: headers_dir = "/path/to/some/dir" becomes something a bit more like 0x09039dc0 = "/path/to/some/dir" by the time the code is actually run. This means that any reference to headers_dir has to get replaced by the numeric reference at compile time, which is what the quasiquoter was for.

Without using quasiquoters or other parts of Template Haskell; you’d have to do something to manually preserve the variable names, such as putting the values in a map.

What’s wrong with quasiquoting? Check out Shakespeare (as mentioned in comments):

{-# LANGUAGE QuasiQuotes #-}
import Text.Shakespeare.Text
import Data.Text

runtimeInterpolatedString :: (ToText a, ToText b, ToText c) => a -> b -> c -> Text
runtimeInterpolatedString a b c = [lt|There once was #{a} that #{b} when #{c}.|]

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa

Why doesn’t Haskell have a ‘format’ function for string interpolation?

I’m trying to use Shake and I stumbled upon the following problem: there’s no easy and convenient way to interpolate a string. I know about Text.Printf — it’s not what I’m looking for. The interpolation syntax I’m talking about is like this:

(Make)

HEADERS_DIR := /some/path/to/dir

CFLAGS := "-g -I$(HEADERS_DIR) -O2"

(Python)

headers_dir = "/some/path/to/dir"

cflags = "-g -I{headers_dir} -O2".format(**locals())

And now compare this to possible Haskell’s solution. Firstly:

$ cabal install interpolatedstring-perl6
$ ghci -XExtendedDefaultRules -XQuasiQuotes

And then:

> import Text.InterpolatedString.Perl6 (qq)
> let headers_dir = "/path/to/some/dir"
> [qq| -g -I$headers_dir -O2 |] :: String

While I think Make goes maybe a step too far in its eagerness to interpolate even when not asked, I wonder why Haskell doesn’t have a format function like Python does. It could parse the supplied string and pull the value with same name as referenced in pattern:

let headers_dir = "/path/to/some/dir"
format "-g -I$headers_dir -O2"

Is there a specific reason why it’s not implemented, or everyone is just happy with Text.Printf‘s verbosity and/or lengthy setup of interpolation libraries?

Update: A lot of people misinterpret the question as asking about general string formatting, with possibility of precision specification in case of integers, etc. The examples provided demonstrate one specific case of interpolation, which is just “substitute the result of show a at the place of name”. It does allow for simpler syntax, and it does not use a variadic function per se.

9

I suspect it’s done as quasiquoting because this will interpolate the string at compile time, and due to the pure nature of functions in Haskell this is possible while other languages lack such ability because of their impure nature.

Think about it, other languages have to do it during runtime each time which is going to be much slower than the compile time once and done quasi-quoted interpolation.

If you want to do it at runtime explicitly then you should be able to do some simple abstractions that take advantage of Haskell’s strings being lists, or you could create a different data structure that’s similar pretty easily – but I would go for the more efficient quasi-quoted approach if I were doing this in any code I actually cared about.

That said, I found on Hackage the Data.Text.Format package which appears to do C# style substitution pretty straight forward, here’s an answer showing an example on SO:
String formatting in Haskell – though as noted by Bryan O’Sullivan and others on that question that answer usess an out-dated package and there’s a newer one Bryan has created (my guess the Data.Text.Format package is his new one that should be used) so the usage may be slightly different from in that SO example, though appears fairly similar.

4

The best typesafe approach I can offer you is the formatting library

{-# LANGUAGE OverloadedStrings #-}

import Formatting (format, (%))
import Formatting.ShortFormatters (t) 

headers_dir = "/path/to/some/dir"

example = format ("-g -I" % t % " -O2") headers_dir

GHCi> example 
"-g -I/path/to/some/dir -O2"

1

updated after question update

I feel that the python version:

"-g -I{headers_dir} -O2".format(**locals())

is an abuse of the language. So I wouldn’t say that python really offers local variable interpolation in strings. In fact, few languages have it.

Answering why language X doesn't have feature Y often comes down to saying that the designers did not feel that it was worth it. In the case of local variable interpolation in strings, it is very much a niche thing used in languages focused on command line scripts. Which Haskell is not. The fact that you can do it in python only comes from the (too?) powerful reflection facilities of the language.

Now why is Text.InterpolatedString.Perl6 so complex to use? It relies on quasiquotations, which is not part of the haskell language. It is a ghc language extension, so you have to declare its usage somewhere. If you exclude the library installation & the language extension declaration, its usage is not really more complex than in your other examples, and is more safe.

3

In Python: the language actually specifies that variables can be referenced by name at runtime. In Haskell: names for everything except top level bindings tend to get erased during compile time and replaced with numeric references.

In your example: headers_dir = "/path/to/some/dir" becomes something a bit more like 0x09039dc0 = "/path/to/some/dir" by the time the code is actually run. This means that any reference to headers_dir has to get replaced by the numeric reference at compile time, which is what the quasiquoter was for.

Without using quasiquoters or other parts of Template Haskell; you’d have to do something to manually preserve the variable names, such as putting the values in a map.

What’s wrong with quasiquoting? Check out Shakespeare (as mentioned in comments):

{-# LANGUAGE QuasiQuotes #-}
import Text.Shakespeare.Text
import Data.Text

runtimeInterpolatedString :: (ToText a, ToText b, ToText c) => a -> b -> c -> Text
runtimeInterpolatedString a b c = [lt|There once was #{a} that #{b} when #{c}.|]

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa

Why doesn’t Haskell have a ‘format’ function for string interpolation?

I’m trying to use Shake and I stumbled upon the following problem: there’s no easy and convenient way to interpolate a string. I know about Text.Printf — it’s not what I’m looking for. The interpolation syntax I’m talking about is like this:

(Make)

HEADERS_DIR := /some/path/to/dir

CFLAGS := "-g -I$(HEADERS_DIR) -O2"

(Python)

headers_dir = "/some/path/to/dir"

cflags = "-g -I{headers_dir} -O2".format(**locals())

And now compare this to possible Haskell’s solution. Firstly:

$ cabal install interpolatedstring-perl6
$ ghci -XExtendedDefaultRules -XQuasiQuotes

And then:

> import Text.InterpolatedString.Perl6 (qq)
> let headers_dir = "/path/to/some/dir"
> [qq| -g -I$headers_dir -O2 |] :: String

While I think Make goes maybe a step too far in its eagerness to interpolate even when not asked, I wonder why Haskell doesn’t have a format function like Python does. It could parse the supplied string and pull the value with same name as referenced in pattern:

let headers_dir = "/path/to/some/dir"
format "-g -I$headers_dir -O2"

Is there a specific reason why it’s not implemented, or everyone is just happy with Text.Printf‘s verbosity and/or lengthy setup of interpolation libraries?

Update: A lot of people misinterpret the question as asking about general string formatting, with possibility of precision specification in case of integers, etc. The examples provided demonstrate one specific case of interpolation, which is just “substitute the result of show a at the place of name”. It does allow for simpler syntax, and it does not use a variadic function per se.

9

I suspect it’s done as quasiquoting because this will interpolate the string at compile time, and due to the pure nature of functions in Haskell this is possible while other languages lack such ability because of their impure nature.

Think about it, other languages have to do it during runtime each time which is going to be much slower than the compile time once and done quasi-quoted interpolation.

If you want to do it at runtime explicitly then you should be able to do some simple abstractions that take advantage of Haskell’s strings being lists, or you could create a different data structure that’s similar pretty easily – but I would go for the more efficient quasi-quoted approach if I were doing this in any code I actually cared about.

That said, I found on Hackage the Data.Text.Format package which appears to do C# style substitution pretty straight forward, here’s an answer showing an example on SO:
String formatting in Haskell – though as noted by Bryan O’Sullivan and others on that question that answer usess an out-dated package and there’s a newer one Bryan has created (my guess the Data.Text.Format package is his new one that should be used) so the usage may be slightly different from in that SO example, though appears fairly similar.

4

The best typesafe approach I can offer you is the formatting library

{-# LANGUAGE OverloadedStrings #-}

import Formatting (format, (%))
import Formatting.ShortFormatters (t) 

headers_dir = "/path/to/some/dir"

example = format ("-g -I" % t % " -O2") headers_dir

GHCi> example 
"-g -I/path/to/some/dir -O2"

1

updated after question update

I feel that the python version:

"-g -I{headers_dir} -O2".format(**locals())

is an abuse of the language. So I wouldn’t say that python really offers local variable interpolation in strings. In fact, few languages have it.

Answering why language X doesn't have feature Y often comes down to saying that the designers did not feel that it was worth it. In the case of local variable interpolation in strings, it is very much a niche thing used in languages focused on command line scripts. Which Haskell is not. The fact that you can do it in python only comes from the (too?) powerful reflection facilities of the language.

Now why is Text.InterpolatedString.Perl6 so complex to use? It relies on quasiquotations, which is not part of the haskell language. It is a ghc language extension, so you have to declare its usage somewhere. If you exclude the library installation & the language extension declaration, its usage is not really more complex than in your other examples, and is more safe.

3

In Python: the language actually specifies that variables can be referenced by name at runtime. In Haskell: names for everything except top level bindings tend to get erased during compile time and replaced with numeric references.

In your example: headers_dir = "/path/to/some/dir" becomes something a bit more like 0x09039dc0 = "/path/to/some/dir" by the time the code is actually run. This means that any reference to headers_dir has to get replaced by the numeric reference at compile time, which is what the quasiquoter was for.

Without using quasiquoters or other parts of Template Haskell; you’d have to do something to manually preserve the variable names, such as putting the values in a map.

What’s wrong with quasiquoting? Check out Shakespeare (as mentioned in comments):

{-# LANGUAGE QuasiQuotes #-}
import Text.Shakespeare.Text
import Data.Text

runtimeInterpolatedString :: (ToText a, ToText b, ToText c) => a -> b -> c -> Text
runtimeInterpolatedString a b c = [lt|There once was #{a} that #{b} when #{c}.|]

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật