2019年9月21日土曜日

YesodでXMLをレスポンスする

XML APIサーバーで使いたい


バックエンドの開発用サーバーを皆に黙って、こっそりYesodで作ろうかと思ってたら、メンテナーがいなくなることが判明し、全員に却下されることとなったが、いつかやってやろうと思っている。


でXML


YesodでXMLを出力する、TemplateHaskellを使うと結構簡単

{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
module Handler.Home where

import Import
import Text.XML
import Text.Hamlet.XML
import qualified Data.Map as M
import qualified Text.XML.Stream.Render as R

getHomeR :: Handler TypedContent
getHomeR = selectRep $ do
    provideRep $ return $ repXml $ renderText rs (getXml 10)

getXml :: Int -> Document
getXml n = Document p elm []
    where
        p = Prologue [] Nothing []
        elm = Element "root" M.empty [xml|
<params>
    <param>#{pack $ show n}
    <param>yyy
|]

rs :: R.RenderSettings
rs = def


Handler部分だけですが、TypedContentとrepXmlでcontent-type/xmlに変えて、Document型を返す関数をrenderText関数へ食わせるだけ。

THとか使わない版


ベタに書くとこんな感じか、オレオレデータをXMLに無理やり変換してるだけ、あまり綺麗じゃないので許してね

{-# LANGUAGE OverloadedStrings #-}

import Text.XML
import qualified Data.Text as T
import qualified Data.Text.Internal as T
import qualified Data.Text.Lazy as L
import qualified Data.Text.Internal.Lazy as L
import qualified Data.Map as M

data Foo = Foo {
    identFoo :: Int
  , namefoo :: T.Text
  , argList :: [Argument]
} deriving(Show)

data Argument = Argument {
    nameArg :: T.Text
  , dataArg :: Maybe T.Text
} deriving(Show)

data Other = Other {
    identOther :: Int
  , nameOther :: T.Text
} deriving(Show)

main :: IO ()
main = putStrLn $ T.unpack $ L.toStrict $
  renderText (def :: RenderSettings) $ createDoc $ (foos createFoo) ++ (others createOther)

createDoc :: [Node] -> Document
createDoc nodes = Document prlg elem [] 
    where
      prlg = Prologue [] Nothing []
      elem = Element (Name "root" Nothing Nothing) M.empty nodes
      
foos :: [Foo] -> [Node]
foos = map (fooNodes)

others :: [Other] -> [Node]
others = map (otherNodes)

node :: Int -> T.Text -> M.Map Name T.Text
node i name = M.fromList [
                   (Name "id" Nothing Nothing, (T.pack $ show i))
                 , (Name "name" Nothing Nothing, name)
               ]

fooNodes :: Foo -> Node
fooNodes f@(Foo i name arg) = NodeElement elem
    where
      elem = Element n
                     (node i name)
                     nodes
      n = Name "foo" Nothing Nothing
      nodes = map (\(Argument an dt) ->
                     NodeElement
                         (Element (Name "argument" Nothing Nothing)
                         (M.fromList [(Name "name" Nothing Nothing, an)])
                         (nodeCont dt))
                  ) arg

otherNodes :: Other -> Node
otherNodes o@(Other i name) = NodeElement elem
    where
      elem = Element n
                     (node i name)
                     []
      n = Name "other" Nothing Nothing

nodeCont :: Maybe T.Text -> [Node]
nodeCont (Just val) = [NodeContent val]
nodeCont _ = []

createFoo :: [Foo]
createFoo = [Foo 1 "test" createArgument, Foo 2 "test2" createArguments]
            
createArgument :: [Argument]
createArgument = [Argument "a" (Just "empty 吉田")]

createArguments :: [Argument]
createArguments = [Argument "b" (Just "エンペラー 吉田"), Argument "c" Nothing]

createOther :: [Other]
createOther = [Other 2 "someother"]

{-
<?xml version="1.0" encoding="UTF-8"?>
<root>
    <foo id="1" name="test">
        <argument name="a">empty 吉田</argument>
    </foo>
    <foo id="2" name="test2">
        <argument name="b">エンペラー 吉田</argument>
        <argument name="c"/>
    </foo>
    <other id="2" name="someother"/>
</root>
-}




とりあえず、吉田さんのとこに上げときます

https://github.com/calimakvo/resp-xml

2019年9月20日金曜日

Shizuoka.php 行ってきた

久しぶりに静岡に行ってきた


ここ最近プログラムを書かなくなって、久しくPHPのバージョンも5.7あたりの記憶しか無くなっていたので、最近のPHP界隈の話を聞けて良かった。

皆さんの資料はこちらです

https://shizuokaphp.connpass.com/event/26794/presentation/

PHPの言語仕様もだいぶ改良されてました、時間取ってまたコード書いてみようと思います。

後の飲み会も、たのしく飲ませていただきました。(2次会以降はクズばかりになったって聞きましたが...)

また、開催されるときは、飲みに行こうかとおもいます、ポリちゃんお疲れでした。

Shizuoka.hs について


何か最近、以前の言語戦争を思わせるようなツイートを目にしたのと、またそれに間違いがあるので、ここで正確な情報をお知らせしたいとおもいます。

 じつは、


こうなんですよ!

そして伊豆半島はかわいいピンク色、そう全部Haskellなんです、皆さん覚えておいてください。
そして、この地図を作ってくださった方が再度正確に修正して下さるということで、安堵してますが、有難うございます。

ついでで申し訳ないのですが、色もそうなんですが、私もgoみたいにかわいいアイコンを作ってはみたものの上手に出来ないので私が大ファンの吉田さんを参考に置いてみました。

こんな感じでお願いします。

この年になって双子抱えて、gentooとか飲酒ととかほんと忙しいのですが、

今年中には 

Shizuoka.hs

ベースは三島haskell無名関数の会)

 やるので、みなさん仲良く静岡で飲もうね。

ちょっと何言ってるか分からないけど、yoropiku...
 

2019年7月28日日曜日

mysql-workbenchのロケールエラー

久しぶりにmysql-workbenchを使おうと思って起動したら、ファイル開こうとすると落ちる。

(mysql-workbench-bin:1061): glibmm-ERROR **: 05:41:45.709:
unhandled exception (type std::exception) in signal handler:
what: locale::facet::_S_create_c_locale name not valid

calimakvo ~ # 

ちょっと調べて見たところ、落ちてる場所は、

cuomo@calimakvo ~ $ nm -D --demangle /usr/lib/gcc/x86_64-pc-linux-gnu/8.3.0/libstdc++.so | grep std::locale::facet::_S_create_c_locale
00000000000d99b0 T std::locale::facet::_S_create_c_locale(__locale_struct*&, char const*, __locale_struct*)
cuomo@calimakvo ~ $ 

なんとlibstdc++のなかではないですか、でそこのコード

void
locale::facet::_S_create_c_locale(__c_locale& __cloc, const char* __s,
                  __c_locale __old)
{
  __cloc = __newlocale(1 << LC_ALL, __s, __old);
  if (!__cloc)
    {
  // This named locale is not supported by the underlying OS.
  __throw_runtime_error(__N("locale::facet::_S_create_c_locale "
                "name not valid"));
    }
}
細かいことは分かりませんが、__clocにロケールカテゴリオブジェクトを返せないようなので、こういうのは、英語のロケールまわりをいじくるのが「定説です」 ...自信はさほどありません

そこで、localeを確認してみる

calimakvo ~ # locale -a
C
C.utf8
POSIX
ja_JP
ja_JP.eucjp
ja_JP.utf8

たぶん、この中のロケールでは足りない可能性があるので、さらに追加してみた

  • /etc/locale.gen を修正し以下のコメントを外す

en_US.UTF-8 UTF-8
  • locale-gen再実行
calimakvo ~ # locale-gen
 * Generating 6 locales (this might take a while) with 8 jobs
 *  (1/6) Generating en_US.ISO-8859-1 ...                     [ ok ]
 *  (3/6) Generating ja_JP.EUC-JP ...                         [ ok ]
 *  (4/6) Generating ja_JP.EUC-JP ...                         [ ok ]
 *  (5/6) Generating ja_JP.UTF-8 ...                          [ ok ]
 *  (6/6) Generating C.UTF-8 ...                              [ ok ]
 *  (2/6) Generating en_US.UTF-8 ...                          [ ok ]
 * Generation complete
 * Adding locales to archive ...                              [ ok ]
めでたくmysql-workbenchが利用可能になりました、まぁ、「言語はローケールは母国語と英語は設定しときなさい」ということらしいです。