haskell-jp / general #13

@noolbar has joined the channel
@ has joined the channel
Qiita の Advent Calendar の某記事でここに興味を持ち Slack を始めました, 見るだけになってしまうかも知れませんが, もしもの時はよろしくお願い申し上げます.
@igarash1 has joined the channel
@ has joined the channel
ぽんちゃん
@ぽんちゃん has joined the channel
Kazuki Yoshida
@Kazuki Yoshida has joined the channel
@てるぞう has joined the channel
はじめまして。Haskell初心者で分からないことだらけですが、頑張りますのでどうぞよろしくお願いいたします。
質問させて頂きます。Haskellのwebアプリ(wai)の勉強をしているのですが、以下のソースコードの24行目、"こんにちわ"の部分が、ブラウザ上で見ると文字化けしてしまいます。文字コード変換の問題かと思うのですが、どうしても解消できませんでした。どうぞお知恵をお貸しください。

{-# LANGUAGE OverloadedStrings #-}

module Lib
( someFunc
) where


import Network.Wai (Application, responseLBS)
import Network.HTTP.Types (status200)
import Network.Wai.Handler.Warp (run,Port)
import System.Environment(getEnvironment)
import Data.List(lookup)
import Data.Maybe


someFunc :: IO ()
someFunc = do
port <- getPort
Prelude.putStr "start Server: http://localhost:"
print port
run port helloApp

helloApp :: Application
helloApp req respond =respond
$ responseLBS status200 [] "こんにちわ" # ← この部分です

getPort :: IO Port
getPort = getEnvironment
= return . port
where
port = fromMaybe defaultPort . fmap read . lookup "PORT"

defaultPort :: Port
defaultPort = 3000
ああー、ByteStringの文字列リテラルの罠ですね。。。
取り急ぎ結論から言うと、
"こんにちわ"Data.Text.Lazy.Encoding.encodeUtf8 http://hackage.haskell.org/package/text-1.2.3.1/docs/Data-Text-Lazy-Encoding.html#v:encodeUtf8 を適用すれば解決するはずです。
IsString ByteStringは罠ですね…
igrep 様、fumieval様、真に有難うございました。ソースコードを以下のように訂正しました所、文字化けが解消しました。大変お世話になり、真に有難うございました。
 Chromeですと、さらにブラウザ自身の文字コードもUTF-8にしないといけないのですね。。大変勉強になりました。(FireFoxはそのままできれいに表示されました。)

import Data.Text.Lazy.Encoding # 追加

hello= encodeUtf8 "こんにちわ" # 追加・変更
grep 様、fumieval様、真に有難うございました。ソースコードを以下のように訂正しました所、文字化けが解消しました。大変お世話になり、真に有難うございました。
 Chromeですと、さらにブラウザ自身の文字コードもUTF-8にしないといけないのですね。。大変勉強になりました。(FireFoxはそのままできれいに表示されました。)

import Data.Text.Lazy.Encoding # 追加

hello= encodeUtf8 "こんにちわ" # 追加・変更
igrep 様、名前のiが抜けてしまっておりました。大変失礼いたしました。申し訳ありませんでした。
詳しく言うと、これはOverloadedStringsを使ってBytStringの文字列リテラルを書いたことによる問題です。
OverloadedStringsを使ってBytStringの文字列リテラルを書いた場合、内部でBytStringのfromStringというStringからBytStringに変換する関数(<@U4KUNQF9N>さんが触れてるIsStringのメソッドです)を呼んでいるのですが、各Charの1バイト目の値しかとらないため、 "こんにちわ" の各文字が切れてしまうのです
Chromeですと、さらにブラウザ自身の文字コードもUTF-8に
そんなことなかった気もしますが、その辺は WAI 関係なく web の話なので、 response header に Content-Type: text/html; charset=UTF-8 加えるなどするのがいいと思います。
@てるぞう すみません、原則として「Also send to general 」は使わないでください。
@igrep 有難うございます。よくわからないまま、チェックを入れてしまっておりました。申し訳ありません。
hiratara 様 有難うございます。また、いろいろ試して、勉強してみたいと思います。
@ has joined the channel
@kawamura has joined the channel
@t-era has joined the channel
@ has joined the channel
@hanyu has joined the channel
抽象的な質問で恐縮ですが、質問させていただきます。
先程hClose を忘れていたせいでoutput の末尾だけ欠損して毎回その数が異なるというバグと戦っておりました。
何かを呼び出した後に、特定の関数を呼び出していない場合にエラーを表示するような機能を付ける場合、template Haskell 等でコンパイル時に判断する他に手段があるでしょうか。
いかなる条件でも絶対に呼び出すことを保証するのは、そもそもTemplate Haskellでも難しいです。
そうしたAPIや型(ファイルの場合 Handle )を実装した人が、 bracket を使って作ったAPI (ファイルの場合 withFile )のみを利用してその型を利用できるようにする、という手はあります。
あと、APIのユーザーとして、 極力 withFile などのAPIだけを利用する、というだけでもそれなりに防げるかと思います。
ありがとうございます.利用者側としては取り敢えずbracketを基本的に使うことを心がけるというのが一番なのですね
オオツカケンタロウ
@オオツカケンタロウ has joined the channel
bracket や、withXXXX を使うのは前提として ResourceT を使うっていう手もあるにはありますよ。
Conduitなら必ずhCloseされるよ定期
実装はResourceTです
@keigon has joined the channel
@skaribe has joined the channel
@koh has joined the channel
@ has joined the channel
@snak has joined the channel
@rot has joined the channel
@murakami has joined the channel
@863 has joined the channel
@madai has joined the channel
@kita127 has joined the channel
@ has joined the channel
@ has joined the channel