Haskellで私のクローン(bot)を書いた
ゆきばらです。ソースコードがいっぱいあって長いです。ごめん。
何をしましたか
ゆきばら のコピー(@ykbr__ai)を作りました。アンダーバーは二つあります。
コードはこれです。積んでいたすごいH本をこのままにはしておけず、Haskellの勉強を兼ねてやりました。@hsm_aiの二番煎じ
環境
OS: Windows 10 Pro
言語: Haskell
- stackのバージョン -> 1.91
やることの方針
やった
環境を作る
Haskellにはstack
という便利なビルドツール?パッケージマネージャ?があり、それを使います。
HaskellでTwitterのタイムライン取得とツイート投稿をやってみた を参考にさせて頂き、とりあえずツイートまで漕ぎ付けました。
一応簡単に説明すると、
stack new
をすると雛型が生成されるpackage.yaml
に使うパッケージを記述する。src/Lib.hs
とapp/Main.hs
にコーディングをする
ということでほぼ写経でしたが、アクセストークンをペーストする際に半角スペースが混入し、これで1時間溶かしました。
認証の諸々は分離させておきます。
MeCabをインストールする
MeCabを絶対にインストールしてくれ!!!!!!!!!!!!(1敗)
当然ですが、MeCab本体が無いとどうしようもありません。これに気付かないと2時間が溶けます。ました。
MeCabのインストールには有志作成のこちら(64bit版)を使用させていただきました。
インストールが終わったらPATHを通してあげましょう。
Windowsなので、環境変数Pathに C:\Program Files\MeCab\bin
を追加しました。
MeCabには標準でHaskellバインディングがありません。
なので、hsmecabというかの有名なtanakhさんが作成したMeCabのHaskellバインディングを少し改良して使います。
とりあえずforkして、依存関係を書き直しました。
そのあと、stack.yaml
に
extra-deps: - github: Yukibara/hsmecab commit: "687dce1" extra-include-dirs: - C:\Program Files\MeCab\sdk extra-lib-dirs: - C:\Program Files\MeCab\sdk
ということを書いてあげます。
extra-deps
にはstackageにないパッケージを記載するのですが、今回はそこに先程依存関係を書き直したhsmecabを書きます。
extra-include-dirs
と extra-lib-dirs
にはMeCabのヘッダファイルとライブラリがある場所をそれぞれ書きました。
ハマる
ここから地獄のハマり芸が始まります。
PS E:\User\Desktop\ykbr-ai> stack build Building all executables for `ykbr-ai' once. After a successful build of all of them, only specified executables will be rebuilt. ykbr-ai-0.1.0.0: build (lib + exe) Preprocessing library for ykbr-ai-0.1.0.0.. Building library for ykbr-ai-0.1.0.0.. Preprocessing executable 'ykbr-ai-exe' for ykbr-ai-0.1.0.0.. Building executable 'ykbr-ai-exe' for ykbr-ai-0.1.0.0.. Linking .stack-work\dist\7d103d30\build\ykbr-ai-exe\ykbr-ai-exe.exe ... E:\User\Desktop\ykbr-ai\.stack-work\install\82b85939\lib\x86_64-windows-ghc-8.4.4\mecab-0.4.0-36pNwJDNccJIAIpRtYgh7y/libHSmecab-0.4.0-36pNwJDNccJIAIpRtYgh7y.a(MeCab.o):fake:(.text+0xb8ae): `mecab_get_theta' に対する定義されていない参照です E:\User\Desktop\ykbr-ai\.stack-work\install\82b85939\lib\x86_64-windows-ghc-8.4.4\mecab-0.4.0-36pNwJDNccJIAIpRtYgh7y/libHSmecab-0.4.0-36pNwJDNccJIAIpRtYgh7y.a(MeCab.o):fake:(.text+0xb9e9): `mecab_version' に対する定義されていない参照です E:\User\Desktop\ykbr-ai\.stack-work\install\82b85939\lib\x86_64-windows-ghc-8.4.4\mecab-0.4.0-36pNwJDNccJIAIpRtYgh7y/libHSmecab-0.4.0-36pNwJDNccJIAIpRtYgh7y.a(MeCab.o):fake:(.text+0xbc3b): `mecab_set_theta' に対する定義されていない参照です E:\User\Desktop\ykbr-ai\.stack-work\install\82b85939\lib\x86_64-windows-ghc-8.4.4\mecab-0.4.0-36pNwJDNccJIAIpRtYgh7y/libHSmecab-0.4.0-36pNwJDNccJIAIpRtYgh7y.a(MeCab.o):fake:(.text+0xbdee): `mecab_get_all_morphs' に対する定義されていない参照です E:\User\Desktop\ykbr-ai\.stack-work\install\82b85939\lib\x86_64-windows-ghc-8.4.4\mecab-0.4.0-36pNwJDNccJIAIpRtYgh7y/libHSmecab-0.4.0-36pNwJDNccJIAIpRtYgh7y.a(MeCab.o):fake:(.text+0xbfbc): `mecab_nbest_next_tostr' に対する定義されていない参照です E:\User\Desktop\ykbr-ai\.stack-work\install\82b85939\lib\x86_64-windows-ghc-8.4.4\mecab-0.4.0-36pNwJDNccJIAIpRtYgh7y/libHSmecab-0.4.0-36pNwJDNccJIAIpRtYgh7y.a(MeCab.o):fake:(.text+0xcaa4): `mecab_nbest_next_tonode' に対する定義されていない参照です E:\User\Desktop\ykbr-ai\.stack-work\install\82b85939\lib\x86_64-windows-ghc-8.4.4\mecab-0.4.0-36pNwJDNccJIAIpRtYgh7y/libHSmecab-0.4.0-36pNwJDNccJIAIpRtYgh7y.a(MeCab.o):fake:(.text+0xcd7e): `mecab_get_lattice_level' に対する定義されていない参照です E:\User\Desktop\ykbr-ai\.stack-work\install\82b85939\lib\x86_64-windows-ghc-8.4.4\mecab-0.4.0-36pNwJDNccJIAIpRtYgh7y/libHSmecab-0.4.0-36pNwJDNccJIAIpRtYgh7y.a(MeCab.o):fake:(.text+0xceb4): `mecab_new2' に対する定義されていない参照です E:\User\Desktop\ykbr-ai\.stack-work\install\82b85939\lib\x86_64-windows-ghc-8.4.4\mecab-0.4.0-36pNwJDNccJIAIpRtYgh7y/libHSmecab-0.4.0-36pNwJDNccJIAIpRtYgh7y.a(MeCab.o):fake:(.text+0xcfd2): `mecab_destroy' に対する定義されていない参照です E:\User\Desktop\ykbr-ai\.stack-work\install\82b85939\lib\x86_64-windows-ghc-8.4.4\mecab-0.4.0-36pNwJDNccJIAIpRtYgh7y/libHSmecab-0.4.0-36pNwJDNccJIAIpRtYgh7y.a(MeCab.o):fake:(.text+0xd258): `mecab_set_partial' に対する定義されていない参照です E:\User\Desktop\ykbr-ai\.stack-work\install\82b85939\lib\x86_64-windows-ghc-8.4.4\mecab-0.4.0-36pNwJDNccJIAIpRtYgh7y/libHSmecab-0.4.0-36pNwJDNccJIAIpRtYgh7y.a(MeCab.o):fake:(.text+0xd341): `mecab_set_partial' に対する定義されていない参照です E:\User\Desktop\ykbr-ai\.stack-work\install\82b85939\lib\x86_64-windows-ghc-8.4.4\mecab-0.4.0-36pNwJDNccJIAIpRtYgh7y/libHSmecab-0.4.0-36pNwJDNccJIAIpRtYgh7y.a(MeCab.o):fake:(.text+0xd5ae): `mecab_get_partial' に対する定義されていない参照です E:\User\Desktop\ykbr-ai\.stack-work\install\82b85939\lib\x86_64-windows-ghc-8.4.4\mecab-0.4.0-36pNwJDNccJIAIpRtYgh7y/libHSmecab-0.4.0-36pNwJDNccJIAIpRtYgh7y.a(MeCab.o):fake:(.text+0xd77c): `mecab_set_all_morphs' に対する定義されていない参照です E:\User\Desktop\ykbr-ai\.stack-work\install\82b85939\lib\x86_64-windows-ghc-8.4.4\mecab-0.4.0-36pNwJDNccJIAIpRtYgh7y/libHSmecab-0.4.0-36pNwJDNccJIAIpRtYgh7y.a(MeCab.o):fake:(.text+0xda5b): `mecab_strerror' に対する定義されていない参照です E:\User\Desktop\ykbr-ai\.stack-work\install\82b85939\lib\x86_64-windows-ghc-8.4.4\mecab-0.4.0-36pNwJDNccJIAIpRtYgh7y/libHSmecab-0.4.0-36pNwJDNccJIAIpRtYgh7y.a(MeCab.o):fake:(.text+0xddb2): `mecab_sparse_tostr2' に対する定義されていない参照です E:\User\Desktop\ykbr-ai\.stack-work\install\82b85939\lib\x86_64-windows-ghc-8.4.4\mecab-0.4.0-36pNwJDNccJIAIpRtYgh7y/libHSmecab-0.4.0-36pNwJDNccJIAIpRtYgh7y.a(MeCab.o):fake:(.text+0xe13b): `mecab_strerror' に対する定義されていない参照です E:\User\Desktop\ykbr-ai\.stack-work\install\82b85939\lib\x86_64-windows-ghc-8.4.4\mecab-0.4.0-36pNwJDNccJIAIpRtYgh7y/libHSmecab-0.4.0-36pNwJDNccJIAIpRtYgh7y.a(MeCab.o):fake:(.text+0xe460): `mecab_nbest_sparse_tostr2' に対する定義されていない参照です E:\User\Desktop\ykbr-ai\.stack-work\install\82b85939\lib\x86_64-windows-ghc-8.4.4\mecab-0.4.0-36pNwJDNccJIAIpRtYgh7y/libHSmecab-0.4.0-36pNwJDNccJIAIpRtYgh7y.a(MeCab.o):fake:(.text+0xe7f3): `mecab_strerror' に対する定義されていない参照です E:\User\Desktop\ykbr-ai\.stack-work\install\82b85939\lib\x86_64-windows-ghc-8.4.4\mecab-0.4.0-36pNwJDNccJIAIpRtYgh7y/libHSmecab-0.4.0-36pNwJDNccJIAIpRtYgh7y.a(MeCab.o):fake:(.text+0xea22): `mecab_nbest_init2' に対する定義されていない参照です E:\User\Desktop\ykbr-ai\.stack-work\install\82b85939\lib\x86_64-windows-ghc-8.4.4\mecab-0.4.0-36pNwJDNccJIAIpRtYgh7y/libHSmecab-0.4.0-36pNwJDNccJIAIpRtYgh7y.a(MeCab.o):fake:(.text+0xecfb): `mecab_strerror' に対する定義されていない参照です E:\User\Desktop\ykbr-ai\.stack-work\install\82b85939\lib\x86_64-windows-ghc-8.4.4\mecab-0.4.0-36pNwJDNccJIAIpRtYgh7y/libHSmecab-0.4.0-36pNwJDNccJIAIpRtYgh7y.a(MeCab.o):fake:(.text+0xef82): `mecab_sparse_tonode2' に対する定義されていない参照です E:\User\Desktop\ykbr-ai\.stack-work\install\82b85939\lib\x86_64-windows-ghc-8.4.4\mecab-0.4.0-36pNwJDNccJIAIpRtYgh7y/libHSmecab-0.4.0-36pNwJDNccJIAIpRtYgh7y.a(MeCab.o):fake:(.text+0xf2b4): `mecab_set_lattice_level' に対する定義されていない参照です E:\User\Desktop\ykbr-ai\.stack-work\install\82b85939\lib\x86_64-windows-ghc-8.4.4\mecab-0.4.0-36pNwJDNccJIAIpRtYgh7y/libHSmecab-0.4.0-36pNwJDNccJIAIpRtYgh7y.a(MeCab.o):fake:(.text+0xf572): `mecab_strerror' に対する定義されていない参照です E:\User\Desktop\ykbr-ai\.stack-work\install\82b85939\lib\x86_64-windows-ghc-8.4.4\mecab-0.4.0-36pNwJDNccJIAIpRtYgh7y/libHSmecab-0.4.0-36pNwJDNccJIAIpRtYgh7y.a(MeCab.o):fake:(.text+0xf762): `mecab_destroy' に対する定義されていない参照です E:\User\Desktop\ykbr-ai\.stack-work\install\82b85939\lib\x86_64-windows-ghc-8.4.4\mecab-0.4.0-36pNwJDNccJIAIpRtYgh7y/libHSmecab-0.4.0-36pNwJDNccJIAIpRtYgh7y.a(MeCab.o):fake:(.text+0xf828): `mecab_new' に対する定義されていない参照です collect2.exe: error: ld returned 1 exit status `gcc.exe' failed in phase `Linker'. (Exit code: 1) -- While building package ykbr-ai-0.1.0.0 using: C:\sr\setup-exe-cache\x86_64-windows\Cabal-simple_Z6RU0evB_2.2.0.1_ghc-8.4.4.exe --builddir=.stack-work\dist\7d103d30 build lib:ykbr-ai exe:ykbr-ai-exe --ghc-options " -ddump-hi -ddump-to-file -fdiagnostics-color=always" Process exited with code: ExitFailure 1
ふふw
解決方法
extra-lib-dirs: - C:\Program Files\MeCab\sdk
↓
extra-lib-dirs: - C:\Program Files\MeCab\sdk - C:\Program Files\MeCab\bin
libmecab.dll
が C:\Program Files\MeCab\bin
にあったのでそれを指定しただけです。
たったこれだけ。なんと1日を溶かしました。ウケる。
それと、前述したPATHを通さないとstack exec {project-name}
したときに何も表示されることなく(エラー一行生えない)終わるので、しっかり通しましょう(一敗)。
正常に動かないそれ、いよいよ何のエラーも吐かなくなった
— ゆきばら (@ykbr_) 2018年11月2日
ここまで「Botをつくる!」と言ってから5日が経過!!!!!!!!!!!!!!!!
コーディングをする
MeCabのテストをしてあげる
とりあえずハマりから抜けたか確認してみましょう。
import Data.Text.IO as TIO import Text.MeCab someFunc :: IO () someFunc = do let text = "頼むので動いてくださいお願いします" mecab <- new2 "" result <- parse mecab text TIO.putStrLn $ result
これを実行すると
頼む 動詞,自立,*,*,五段・マ行,基本形,頼む,タノム,タノム ので 助詞,接続助詞,*,*,*,*,ので,ノデ,ノデ 動い 動詞,自立,*,*,五段・カ行イ音便,連用タ接続,動く,ウゴイ,ウゴイ て 助詞,接続助詞,*,*,*,*,て,テ,テ ください 動詞,非自立,*,*,五段・ラ行特殊,命令i,くださる,クダサイ,クダサイ お願い 名詞,サ変接続,*,*,*,*,お願い,オネガイ,オネガイ し 動詞,自立,*,*,サ変・スル,連用形,する,シ,シ ます 助動詞,*,*,*,特殊・マス,基本形,ます,マス,マス
良さそうですね。これが出なかったあなたはまだハマっています。トンネル効果でもなんでもいいので抜け出しましょう。
@ykbr_のツイートを取得する
自分のツイートを取得しました。
これはソースコード載せたところでなあという感じなのでリポジトリ見てください(丸投げv0.2)。
いよいよ、これを引数にとってマルコフ連鎖させます。
マルコフ連鎖する
こちらのサイトを死ぬほど参考にしながらマルコフ連鎖をしました。
Haskellはデータ型を作るのが楽なので、
data Word = Begin|Middle String|End deriving (Eq,Show, Generic)
という感じで単語の管理をしました。詳しくはソースを見てください(丸投げの時代)。
#はじめてのツイート
進捗が出ないのですが、25人いない無賃で働くプロコンスタッフ」
— ゆきばら のコピー (@ykbr__ai) November 3, 2018
感想
環境構築がつらかった。
型まわりのエラーでめちゃくちゃハマってHaskellやめちまえになりました。
でもなんとなく書いていて楽しさがあるので、まずはH本を読もうと思います。
あと高専祭でライブコーディングできたのは良かったですね。
今後
とりあえずRTを含んでしまっているのでそれを除外します。
あと自動フォロバを早くつけてくれ。
単語をDBにシュッとやれればかっこいいと思うけどその辺は気が向いたらやろうかなって思います。