ChatGPTに聞いてみたところ、modelを切り替えながら処理する場合どうするか、だいぶ複雑にはなる。あまり見慣れないコードだけど、これで動くようになる。(家計簿で、口座間移動処理データを同時に2つ削除するときのslotの部分)
2025年11月14日金曜日
Qtで、同時に2つのmodelを扱う例
C++の参照、ポインタ復習
Qtで、最近ほとんど使ってなかったポインタや参照をC++で久しぶりに使うことになったが、ほとんど忘れていた。少し復習してみた。
using namespace std;
int func(int& x);
int func2(int* y);
int main(void){
int a=10;
int &b=a; //参照渡し (1)
printf("%d\n",b);
b=11;
int b2=a; //コピー渡し
printf("%d\n",b2);
b2=12;
int *c=&a; //参照
printf("%d\n",*c);
char* e="a";
printf("%s\n",e);
// 関数の引数でも同様
int d=func(a);
printf("%d",d);
int g=func2(&a);
printf("%d",g);
}
int func(int& x){ //参照 渡し ①
return x;
}
int func2(int* y){ // ②
return *y;
}
・&xはxのアドレス *yはyがアドレスのときの値 なので、&と*は逆関数の関係ともいえそう。 *(&x) == x &(*p) == p
2025年11月10日月曜日
Qtでいろいろ作成
家計簿、スケジューラ、日記は、これまで.Net使った自作アプリを使ってきたが、今後Linuxでも使えるようにするため、すべてQtで作り変えることにした。スケジューラと日記はほぼ完成する。日記は、SQlite保存なので、暗号化したテキストで保存することにした。.NETに比べると復号が入っても検索処理も圧倒的に早くなっている。(.NETだと遅すぎて暗号処理を諦めていたけれど、Qtはその点心配はないようだ。)
昨今は、C++に変わり、Rustあたりが速度を要求されるアプリに使われつつあるということだけれど、QtでC++も悪くないように思う。
2025年11月9日日曜日
QtでSqliteつかいたいとき
CMakeList.txtに以下3行追加必要
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets Sql)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets Sql)
target_link_libraries(QtDiary PRIVATE Qt${QT_VERSION_MAJOR}::Widgets Qt${QT_VERSION_MAJOR}::Sql)
git pullのエラー解決 (覚書)
error: Your local changes to the following files would be overwritten by merge: CMakeLists.txt.user Please commit your changes or stash them before you merge. Aborting
この場合、git stash > git pull > git stash pop を試してみる
CMakeLists.txt.user は通常 IDE のユーザー固有設定ファイルなので、プロジェクトによってはバージョン管理に含めないこともあるとか(.gitignore に追加したほうがいい)
<<<<<<< Updated upstream
(リモートの変更)
=======
(自分の stash の変更)
>>>>>>> Stashed changes となっているので、===や<< >>を削除し、どちらかを残す
2025年11月8日土曜日
Qtのandroidへのデプロイ(備忘録)
環境変数 setxで永続保存
setx JAVA_HOME "C:\Program Files\Android\Android Studio\jbr"
setx ANDROID_SDK_ROOT "C:\Users\<ユーザー名>\AppData\Local\Android\Sdk"
setx ANDROID_NDK_ROOT "C:\Users\<ユーザー名>\AppData\Local\Android\Sdk\ndk\29.0.14206865" のように
NDKがないときインストール必要(CMAKEも)
Qtで プロジェクト>キットの管理...>デバイスでAndroidが追加できるが、他の項目をチェックしてまだ不十分なところ(SDKsの赤字のところSdkCommandLineToolなどあれば)をAndroidStudioのSDK Managerで設定していく
・OpenSSLダウンロードなども
スマホ側設定:「設定 → 開発者向けオプション」を有効化→ 「ビルド番号」を7回タップして出ます。「USBデバッグ」をオンにする システムの開発者向けオプションの設定で
がインストールされていること(=adbコマンドが使える)。Qt Creator が SDK/NDK/JDK を認識している。(ツール → オプション → Devices / Android を確認)
adb devices→ device と表示されれば接続成功。
(C:\Users\<ユーザー名>\AppData\Local\Android\Sdk\platform-tools\adb.exeのパスも通しておく必要あり、コントロールパネルあたりから) |
Qt が自動で.apk をビルドスマホへインストール>アプリを起動
QtのWindowsでのデプロイ方法
マルチプラットフォーム言語のため、デプロイ方法は少し手間がかかる。
mingwの形式でビルドした場合
Release ビルドの exe があるディレクトリに移動して、
cd C:\Users\****\kjog\build\Desktop_Qt_6_9_3_MinGW_64_bit-Release
windeployqt.exe のフルパスを指定して実行する必要がある。
"C:\Qt\6.9.3\mingw_64\bin\windeployqt.exe" kjog.exe
2025年11月1日土曜日
ESP32 DEVKIT_Cで容量をWIFIでロギング
2025年10月30日木曜日
PIC12F1822で間欠ブザー
2025年10月29日水曜日
PIC12F675のタイマー修正
以前つくったタイマーのコード修正してみた。すでにPICを基板に半田づけしてしまったが、PicKITに合わせてコネクタをつけてPICにエナメル線で配線しなんとか、書き込みできるようにしてみた。コードを少し変更して、時間ずれも調整してみた。1割ほど時間が短いので、11/10をかけてみた。だいぶ正確になる。
2025年10月28日火曜日
PIC12F1822のCPS 再挑戦
静電気測定ということで、PICのCPSを内臓クロックで使ってみたが、温度の影響のためか、変動が大きい気がしたので、12MHzのXtalを使ってみた。ヤフオクで、10pfコンデンサと一緒に購入。
2025年10月26日日曜日
Qtで、UIデザイナでMainWIndowにWidgetを配置する
C#とは、コントロール(Widget)の配置の仕方が違うので少しとまどいました。
別ウインドウに表示はしやすいのですが、メインウインドウ内に配置するには、レイアウトの指定が必要なようです。
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
table = new KakeiboTable(); // 親は addWidget() で設定されるので不要
ui->centralwidget->layout()->addWidget(table);
}
上記コードだけでは、エラーになります。centralwidgetにテーブルビューを配置したい場合は、cetnralwidgetをオブジェクトインスペクタで選択したら、メニュー>フォームエディタから、レイアウトの方法を指定する必要がありました。ここらへんは、Qt独特のところで慣れが必要なところかもしれません。
MainWindow *w = new MainWindow();
w->show();
2025年10月22日水曜日
Git復習
fetch → リモートの最新履歴を取得
reset --hard → ローカルの土台をリモートに合わせる
stash pop → 退避していた変更を土台の上に戻す
commit → 作業を正式にコミット
push → 安全にリモートに反映
Qtのクロスプラットフォームでの開発 覚書
github経由で、winでもlinuxでもコードを開発できるようにするには
git fetch # 最新のリモート状態を確認
git pull # ローカルブランチに統合(最新化)
# ↓ コード修正(Linux/Windowsどちらでも同じ)
できたらpush
🔹 注意点
改行コードや文字コードの吸収
Git: .gitattributes に * text=auto
Qt: Qt::endl / QTextStream を使う
pull前にfetchで確認
2025年10月20日月曜日
QtCreatorをLinux Mintにいれてみた ~Flatpakについての覚書~
Flatpakでインストールした場合、サンドボックス化されているため、ショートカットを自分で作成することになるようです。
Flatpak ショートカット作成の基本フロー:
①flatpak listでApplication ID を確認 例: io.qt.QtCreator
②#!/bin/bash
flatpak run io.qt.QtCreator を作成し、実行権限不可
③デスクトップショートカット作成ならば .desktop ファイルの Exec= にスクリプトや flatpak run <アプリID> を指定
Exec=flatpak run io.qt.QtCreator
2025年10月18日土曜日
IC-705のAMラジオ用アンテナ
手軽にAMラジオをIC-705で聞けないか、フェライトバーアンテナを試してみた。今、入手が難しくなっているらしいけれど、ヤフオクでラジオから取り外したと思われるものをたまたま見つけて290円で落札させていただいた。1次側が670uHほどだったので、共振周波数から容量を計算すると中波なら40pF前後を並列につなぐ必要がある。たまたま半固定の小型バリコンがあったので、2個並列でつないで、2次側を無線機のアンテナ側につなぐ。窓のそばで位置やバリコンを調整すると、59+20dBと、十分な感度。意外とフェライトバーアンテナのゲインは高いようだ。
2025年10月15日水曜日
VY24G/D i5-520MにLinux Mint
i5-520Mは第一世代で、Win11も23H2までは、SSD化や4GBメモリで騙しだましつかってきましたが、さすがに25H2は、かなり無理がありそうだったので、諦めてLinuxを試すことに。ところが、標準インストールだとなかなかうまくいきません。しばらくして、原因がつかめました。
・BIOSでUSBメモリ選択では、読み取れずUSB HDD選択で読み取れました。(DVDでは遅すぎて無理があります。USBメモリを使いましたが、なぜかUSB HDDを選択しないとだめでした。)
・標準インストールだと最近のLinuxはほとんどGPTのため、うまくいきません。事前にMBR(msdos)に変更が必要です。ここが一番のネックのようです。
Linux Mint ,MX Linuxあたりに候補をしぼりましたが、最終的にMint xfceにしてみました。Windowsと配置が似ていて使いやすい感じがします。注意点としてはGPartedであらかじめ、MBRのパーティション(/,swap./home等)を作っておき、Mintのインストーラでは、新規インストールせずに、カスタマイズのほうを選択して、マウント処理とブート領域設定していきます。途中、警告らしきメッセージも出ますが、無視して進めたところ、うまくいきました。第一世代のCPUは想定していないようですが、しばらくは、PCを無駄にせず、動画視聴等に活用できそうです。
2025年10月14日火曜日
Win11の25H2を古いPC(第3~4世代)に入れる場合の覚書
ノートA573などの第3世代でも、工夫次第でぎりぎり25H2が入るようです。一回目起動しなくなったので、なんとかならないかとChatGPTの助けを借りて、うまくいきました。
H97M-PLUS i5-4460 も使っていますが、こちらも同様な方法でうまくいきました。
Bios(F2キー断続押しで起動するとOk)セキュアブートをoffとするといいようです。そのためには、A573のBIOSでは一時的に管理者パスワード入れないと編集できないようでした。
CSM(互換モード) Enabled 古いOS/MBRディスクとの互換性を確保
Secure Boot / OS Type Disabled または Other OS Windows 11の署名チェックを回避
Fast Boot(高速モード) Disabled 起動チェックを省略せず、SSD/USBを確実に認識
Boot Priority / Legacy First Legacy First ON 古い形式(MBR/USB/SSD)を優先して起動
⚡ Fast Bootは速度優先、Legacy Firstは互換性優先の意味
〇インストールUSB作成 Rufusなどで作成
パーティション形式:MBR(UEFI + CSM対応)
ファイルシステム:NTFS(容量大きめの場合)
「TPM・Secure Boot回避オプション」を有効にするとより安全
GPT形式に変換してUEFI純正起動
CSMを無効、OS Typeを「Windows UEFI mode」に戻すと、Secure Boot利用可能
古いPCでも安定してWindows 11を使える
第3~4世代でギリギリライン
安定して使うなら、Windows 10延命 or Linuxを検討
2025年10月5日日曜日
Haskell入門 型以外の安全性の確保 P286
actionIO action = do
mv <- newEmptyMVar --スレッド間通信用の空のMVarの箱をつくる
_tid <- forkIO $ do --スレッドをたてて
result <- try action --actionを実行 成功ならRight 値 例外なら Left eを返す
result <- takeMVar mv --メインスレッドでMVarから結果を受ける。入るまで待つ動作。
case result of つまり、actionが終わるまで待って結果を受け取る
Left e -> throwIO e
Right r -> return r
久しぶりに室内MLAアンテナでDX
18MHzバンドで久しぶりDXが開けていた。ゼヤ(Asiatic Russia)の局長さんとFT8で交信できた。5Wの室内アンテナで届いたので、コンディションがよかったようだ。
FT8でオンエアしている局の密度をみると、やはり、欧州、日本、北米が目立っているのがわかる。
2025年9月30日火曜日
Haskell入門 モナドによるDSLの実現 ~operational~ P274
型の変換を細かく追って、整合性を確認はしてみましたが、けっこう込み入っていて、それに気を取られると全体の構造がわかりにくいので、おおまかにとらえることも大事かと思いました。runSalesTという関数が、再帰を使って、レシピを読み取っていく構造になっているようです。
その際、ポイントが :>>=という関数のようです。 (ひとつの命令):>>= (それに続く残りの命令) この残りの命令である右辺がkとなっていて、 これが次のrunSalesTへ再帰で渡される構造になっているようです。そして、次のrunSalesTで、また先頭の(ひとつの命令)が取り出され、それに応じて枝分かれした処理が行われ、...これを繰り返していく。
ちょうど、リストを順に処理していく再帰と同じ構造のようです。func( [a:k])=(何らかの処理 func(k)) の形。
簡単なoperational使ったDSLのコードをChatGPTに頼んで作ってもらいました。
sample.hs
2025年9月29日月曜日
Haskell入門 Applicativeスタイル パーサー P251
countRead :: Read a => Int -> Parser Char -> Parser a
countRead i = fmap read . count i
ymdParser :: Parser YMD
ymdParser = YMD <$> countRead 4 digit <*> countRead 2 digit <*> countRead 2 digit
1. YMD は関数:データコンストラクタ YMD は、単なる値ではなく
YMD :: Int -> Int -> Int -> YMD という「Intを3つ受け取って YMD を返す関数」でもある。
2. countRead の役割:countRead n digit は「数字を n 個読み取り、それを整数として解釈する」パーサーである。
例えば: countRead 4 digit :: Parser Int(年を読む)
countRead 2 digit :: Parser Int(月や日を読む)
3. <$> で最初の適用:(<$>) :: (a -> b) -> Parser a -> Parser b
a = Int b = Int -> Int -> YMD 関数 f = YMD 値 Parser a = countRead 4 digit
したがって: YMD <$> countRead 4 digit :: Parser (Int -> Int -> YMD)
ここで、Parser の中には「年をすでに受け取った部分適用関数 YMD y」が入っている。
4. <*> で次々に引数を渡す:次の <*> により
Parser (Int -> Int -> YMD) <*> Parser Int :: Parser (Int -> YMD)
さらにもう一度 <*> を使うと:
Parser (Int -> YMD) <*> Parser Int :: Parser YMD
※イメージ表せば
<$>:外の関数を箱に入れる <*>:箱の中の関数に箱の中の値を渡す
2025年9月27日土曜日
Haskell入門 Readerモナド P186
cons1 <- consume
cons2 <- consumue
constOthers <- local (\e->e{powSaveMode =True}) $ do
cons3 <- consume ① ②
cons4 <- consume
return (cons3 + cons4}
return (cons1+cons2+consOthers)
① ② ①がモード切替の関数 ②do以降が対象
「最初2回通常モード後半2回がSaveモードで電力を測定したものをすべて合計」というレシピをつくり(③のdo以降)それに、testrunのenvでその都度PowerEnvを入れてやる。そんな、流れでしょうか。
( ) `runReader` env は runReader ( ) env ということ?のようです。( )が未適用のところでここに③のdo以下のレシピがくるような、部分適用かと。
Haskell入門 P179 Alternative型クラスでMaybeを使う
do age <- lookup "honma" assocs <|> lookup "hiratara" assocs ①
guard $ age < 20 ②
return age
②が、分かりづらかった。
guard True = pure () つまり Just ()
guard False= empty つまり Nothing
「do式でMaybeを使った場合、①や②のどの行であっても、Nothingが出たらそこでストップして、Nothingを返す(つまり全体の結果がNothing)。最後まで行けばJust ageですが。」
2025年9月26日金曜日
Haskell 代数的データ型、レコード記法(data)とnewTypeについて
型コンストラクタ名 =データコンストラクタ名 フィールドの型1 フィールドの型2,,,
(新しい型の名前=型構成子) (値構成子) (構成要素1,2,,,,)
データコンストラクト名を関数として扱い、Int,String,,,という型の引数に適用するとBookInfoの型の新しい値を生成できる myInfo=Book 978~ "〇〇" ....
〇 data Bool = False | True 代数的データ型 パターンマッチで使用
〇 レコード記法:フィールドに名前
data Employee = NewEmployee { employeeAge :: Integer , employeeName::String,...}
employee = NewEmployee { employeeName="~ ,em~ }
employeeName employeeで名前にアクセスできる アクセサは関数
〇newType NewtypeInt = N Int deriving (Eq,Ord,Show) N 1< N 2は Ordで可、+不可
data DataInt = D Int deriving (Eq,Ord,Show)と比べると制限がある
・ちょうど一つのフィールドのみ可 newType Okay=ExactlyOne Int
・パラメータは問題なし newType Param a b = Param (Either a b)
レコード記法も可 ただしフィールド無は不可 複数の値構成子も不可
newType NTIndexed a =NewNTIndexed { unNTIndexed :: (Integer,a)} deriving Show
NewNTIndexedとunNTIndexedが、NtIndexed aと (Integer,a)を行き来するための関数として使えるのが便利らしい。
Haskell 型クラスについて
Java Haskell
インターフェース 型クラス 型がもつべきメソッドを規定
具象クラス インスタンス 規定されたメソッドの実装
インスタンス 値 個々のデータ
class BasicEq a where ← BasicEqという型クラスを宣言
isEqual :: a -> a -> Bool インスタンスの型はaで表現
isEqal x y = not (isNotEqual x y) ←このようなディフォルト実装あれば、インスタンス
isNotEqual :: a -> a -> Bool で繰り返しの実装を省力化できる
isNotEqual x y= not (isEqual x y)
この型クラスのインスタンスである型は この型クラスの中で定義されている関数を実装しているならどんな型でもいい。 この型クラスでは1つだけ関数を定義している。
関数の型を並べるときにその名前(a)をインスタンスのクラスを表すのに使うことが必要。
:t isEqualを確認すると
isEaqualの定義は
instance BasicEq Bool where
isEqual True True = True
isEqual False False =True
isEqual _ _ =False
instance BasicEq Color where
isEqual Red Red = True
..... のようにインスタンスの種類を増やせる
2025年9月22日月曜日
Haskell入門 P390
サーバー側のビルドがうまくいかず、苦労していたけれど、deriveJSONエラーが、どうやら、上にあるものですでに処理されているものを、下の方で使うということらしい。順序を次のように変えてみたら、うまくビルドできた。最近の仕様は厳しくなっているのかもしれない。
deriveJSON defaultOptions ''AuctionItemId
deriveJSON defaultOptions ''ItemId
deriveJSON defaultOptions ''NewItem
deriveJSON defaultOptions ''Item
deriveJSON defaultOptions ''Term
deriveJSON defaultOptions ''NewUser
deriveJSON defaultOptions ''UserId
deriveJSON defaultOptions ''Inventory
deriveJSON defaultOptions ''AuctionRequest
deriveJSON defaultOptions ''AuctionServerRequest
deriveJSON defaultOptions ''AuctionException
-- deriveJSON defaultOptions ''UUID
deriveJSON defaultOptions ''User
deriveJSON defaultOptions ''AuctionItem
deriveJSON defaultOptions ''AuctionResponse
deriveJSON defaultOptions ''AuctionServerResponse
2025年9月18日木曜日
クラウド経由の家計簿データ保存
これまで、raspiにテキストデータとして、外出中の買い物データを保存して、自作家計簿ソフトでインポートするようにしていたけれど、実際、旅行中など使ってみると、削除や編集の機能もないと不便だった。そこで、sqlite3を使って、raspiのbottleはWebAPI形式にしてみた。
スマホはjavaでCRUDができるようにしたが、これが一番時間がかかった。完全にMVCに則ってコーディングするため、メンテはしやすいだろうけど、最初はなかなか大変。画面の該当行を長押しで、編集・削除もできるようにしたところ、けっこう便利になった。一般のクラウドでとなると、維持費もまあまあかかると思うので、個人利用なら、やはり、raspiが一番の節約になりそう。
raspiは、省エネのわりに、SSRと組み合わせてタイマー機能、タッチパッドPC起動、ネットラジオ録音とさまざま活用できて手放せない存在になっている。
2025年9月6日土曜日
gitのリモートへのクローン(備忘録)
githubにも、方法が表示されますが、念のため手順をまとめてみました。最近は、公開鍵も使うようになっているので。
・ echo "# My Project" > README.md git add .
git commit -m "first commit"
・リモート側で空リポジトリ作成
(例: GitHubで myproject を新規作成)
・ ssh-keygen -t ed25519 -C "your_email@example.com"(または -t rsa でもOK)>公開鍵 (~/.ssh/id_ed25519.pub) を GitHub の[Settings] → [SSH and GPG keys] → New SSH key に登録(アカウントのほうのSettingsで)>(~/.ssh/config)につぎのようにして443ポートを使うように指定、ルータのフィルタリングを通過させたい場合必要
Hostname ssh.github.com
Port 443
User git
・ssh -T git@github.com で接続確認
・git remote set-url origin git@github.com:ユーザー名/リポジトリ名.git
によりパスワード不要になる。
・ローカルのブランチ名が master の場合は git branch -M main で統一
・git push -u origin main
git add .
git commit -m "commit_$1"
git push -u origin main
2025年9月4日木曜日
wslでtomcat10
root権限で ネット上の情報を参考にwslでtomcat10を動かしてみた。
tar -xzvf apache-tomcat-10.1.44.tar.gz
apache-tomcat-10.1.44/bin/startup.sh で起動
apache-tomcat-10.1.44/bin/shutdown.sh で停止
localhost:8080でWindowsからも見ることができた。
<role rolename="manager-gui"/>
<user username="admin" password="pass" roles="manager-gui"/>
2025年9月1日月曜日
Haskellのテストの仕様について
・テストファイルひとつならSpec.hs のままでも OK
しかし、複数だと、Main.hsとしないとだめな仕様になっているようです。このへんは、気づきにくいところ。
・cabalファイルにはpackage.yamlの設定が反映されるけれど、個別のファイルの設定は反映されず、globalスコープのdependencies:のところに、依存関係を記述しないとだめだった。
dependencies:
- base >= 4.7 && < 5
- text
- bytestring
- aeson
- sqlite-simple などのように
2025年8月31日日曜日
Haskell Scottyをapache転送で外向けに
内部LANでのサーバ稼働はうまくいったので、外向けに以前設定したraspi2のapache転送をそのまま利用することにした。ただ、これも一筋縄でいかなかった。(クッキーを利用する場合は、転送処理は難しいようなので、あくまで簡易的な利用にとどめる予定)
・sudo nano /etc/apache2/sites-available/default-ssl.confで、以下のような行を追加
ProxyPass /hs http://追加ラズパイのローカルipアドレス:3000
これで、外部からsslでhttps://ホスト.ドメイン/hsでアクセスすると追加raspi3の3000ポートに転送される。
他に苦労したところでは、
・raspi間の転送がうまくいくように、ルータのipフィルタリングの許可設定を追加
・webアプリに0,0,0,0でリスンするようにコードを書き換える必要があった。そうしないと、なぜか転送がうまくいかなかった。なお、キャッシュが残っているとうまくいかないこともあるので、ビルド、ブラウザは適宜、キャッシュクリアの操作が必要かも。あと、warpを.yamlに追加する必要があった。
app/Main.hs
2025年8月30日土曜日
Haskell入門 Webアプリ(覚書)
10章のWebアプリを読み終えたのはいいけれど、Spockは実際にビルドしても、依存関係のエラーでかなり面倒なことが判明。いろいろ、バージョンを変えて調整したが、ネット上の情報も少なく諦める。せっかくのSpockの勉強も無駄?になったようで、ちょっと回り道してしまった感じもある。
とりあえず、Scottyあたりが、比較的メンテもされているようなので、そちらを試すことにした。まずは、簡単なコードをしばらくしまい込んでいたraspi3で、動作確認をしてみた。
・package.yamlについて: executables>sample-exe>dependenciesに
- sample
- http-types
- aeson
- scotty
stack exec sample-exe でhttp://raspiのアドレス:3000/でアクセス
2025年8月25日月曜日
Haskell入門P368 ルーティング、本体
HaskellでSpockを使ったルーティングは、慣れるまで大変そうですが、無駄のない構成という感じがします。
2025年8月24日日曜日
Haskell入門 P364 グラフ表示部の実装
2025年8月22日金曜日
Haskell入門 P354 各種操作の実装
Haskell入門 P352 コントローラの開発
先ほどコンテキストにはWRContextを使うものとしてsrc/Web/Core.hsに定義しました。
しかし、/のコンテキストは必ず()になるため、WRContextは適しません。そのため、ルーティングに用いるWRAppでは()にも対応できるよう、ctxを指定できるよう定義しています。一方で、ロジックを実際に記述するWRActionのコンテキストは、()を受け取らないようにできるため、型変数ではなくWRContext固定としています。このため、ルーティングの根本でコンテキストをWRContextに設定する必要があります。」
この部分がよくわからなかった。どうやら、型変数ctxの例がWRContextという型などであるようだ。WRappとWRActionは厳密に関連しているのかと思ったけれど、必ずしもそういうことではなかったよう。WRAction が型変数をとらない理由は、型を固定して型安全にしたいからのよう。WRApp はルートや URL ごとに ctx が異なる可能性があるので型変数で柔軟にしている。そういうことらしい。WRappは設定データだから、いろんなデータを設定できる方がいい、でもWRActionは、安全性が求められるのである程度使える設定データは制限したい、そんな感じだろうか。
2025年8月21日木曜日
Haskell入門 P347 ユーザー登録のためのINSERT
仕組みがわかりにくかった。
2025年8月18日月曜日
Haskell入門 P326 処理のまとめ
Haskell入門 P323 テストようやく終了
本のままでは、動かず新しいバージョンに合わせた修正が必要だった。
左辺の(JqQueryObject o) vは{"name":.name,"age":.age}::[(Text,JqQuery)]右辺の fmap $ flip executeQuery v のflipは引数を逆順にして、部分適用を意図した 通りにするために使う。(flip executeQuery v) q == executeQuery q vfmap (fmap $ flip executeQuery v) は、内側のfmapで( , )への処理を、外側のfmapで上の関数使って[ , , ]への処理を行う。sequenceは①で Eitherを外に出していく [(either Text (Text,Value))]②で Ehter Text [(Text,Value)]にする
パーシングは、なかなか複雑
2025年8月16日土曜日
Haskell入門 P318
スペースがある場合のパース
Spec.hs
2. lexeme :: Parser a -> Parser a
lexeme = L.lexeme sc
目的:トークンを読んだあと、自動で空白をスキップする
使い方:
lexeme L.decimal -- 数字を読み取ったあと、空白を消費
lexeme (some letterChar) -- 識別子を読み取ったあと、空白を消費
イメージ:
入力: "123 "
lexeme L.decimal → 123 を返す、空白も消費ない場合は、後ろの空白が残り、パースが失敗しやすくなります。
3. symbol :: String -> Parser String
symbol = L.symbol sc
目的:記号(キーワードや演算子)を読んだあと空白をスキップ
例:
symbol "." -- ドットを読み取り、空白も消費 symbol "[" -- 左ブラケットを読み取り、空白も消費 内部的には lexeme (string s) と同じような働きです。
4. schar :: Char -> Parser Char
schar c = lexeme (char c)
目的:単一文字のトークンを読み取り、空白をスキップ
文字 . や [ ] の後ろに空白があっても問題なくパースできる
例:
schar '.' -- "." と後ろの空白をまとめて消費 schar '[' -- "[" と後ろの空白をまとめて消費
・type Parser = Parsec Void String: Void エラーの型(ない) String 入力の型
Parsecのほうがカスタマイズしやすい Parser a=Parsec Void String a a:結果
・filterRest = try parseIndex <|> try parseField <|> pure JqNil
try:失敗して消費しないなら <|>の右へ 失敗して消費したら<|>の右は試さない
消費の意味:対象テキスト ab でパーサーacなら消費する、対象テキストcdでパーサー
efなら消費してない
・ name <- lexeme (some letterChar)
someは1回以上繰り返し letterChar: a~zA~Zのパース
・ rest <- option JqNil (schar '.' *> filterRest <|> parseField)
option:: a -> Paser a -> Paser a
ディフォルト値 試すパーサ 失敗したらaのディフォルト値返す
Haskell入門 P316 修正コード
P316のコードが動作しなかったので、ChatGPTから同等のものに書き直してもらったのがこちら。新しいライブラリMegaparsecを使うといいらしい。
Parser.hs
Parser a = Parsec Void String a
限られた使い方 aが結果 Parsecのほうがカスタマイズしやすいといえる
・try paraseIndex <|> try parseField <|> pure JqNil で<|>は左が失敗したら右ためす
tryは 失敗しても入力を消費せず次を代わりにためす (入力を巻き戻す)
・some letterChar : some 1回以上繰り返し letterChar a~zA~Zのパース
・option JqNil (char '.' *> filterRest <|> parseField)
option:: a -> Parser a -> Parser a
ディフォルト値->試すパーサ->失敗したら ディフォルトaを返す
char '.' *> filterRest : .を消費し、filterRest返す
ここではtry不要。すでにfilterRestの中でtryは終えているので
Haskell入門 P316
結局、コードが古くてうまく動作せず、別のライブラリを使うことになった。
でも、いちおう、古いほうも、コードをいろいろ確認してみた。
・showParserResult $ parse (jqFilterParser <* endOfInput) s `feed` ""は
showParserResult $ (parse (jqFilterParser <* endOfInput) s) `feed` ""と同じ意味
<* endOfInput 該当しないところはパースせず `feed` ""はパース停止の決まり文句のようなものらしい
・fmap pack $ many1 (letter <|> char '-' <|>..... digit())について
many1 は letter <|> char '-' <|> ... <|> digit は 1文字分のパーサー
many1 (...) はこれを 1回以上繰り返して成功した結果をリスト [Char] にまとめる
fmap pack によって [Char] → Text に変換 letter :: Parser Char なので many1 letter :: Parser [Char] になります。
箱(Parser)はそのままで 中身 [Char] が Text に変わる
・JqIndex <$> パース1 <*> バース2 の意味について復習
<$>で最初に部分適用の関数ができて、その関数のまだ未適用な部分に<*>を順次適用していくしくみ
パーサの場合、関数がつぎつぎと、無限に適用できる引数があるようなもの。その場合は、つねに、部分適用な関数のままでJqIndexが残ることになるといえそう。再帰状態になるのかも。
2025年8月13日水曜日
Haskell入門 P315 パーサの作成
本のコードのままではだめで、けっこう厳密さが要求された。バージョンの違いか?
・Text と String は別物 (T.pack ".")で Textに
・コンストラクタもエクスポートリストで見えるようにする (..)など利用
・stack.yaml / package.yaml の依存関係はビルド対象ごとに確認(ライブラリも指定)
Parser.hs
Hjq.hs
package.yaml
Haskell入門 P314 HUnitによる自動テスト
ただ、本の内容はバージョンが古くそのままでは動かなかった。
・Test suite not yet implementedとでるので
package.yamlにtest:hjq-test:dependencies:のところに - HUnitを追加
Spec.hs の先頭にimport Test.HUnit 追加
・文字エンコードでエラーがでるので
Dosプロンプトのショートカットに cmd /k "chcp 65001 && cd パス"のように、事前にエンコード切り替えをいれる
・runTestTTの型が新しいバージョンでは 返り値が IO Countsというものらしいので
以下のようなコードにするらしい。
import Test.HUnit
import System.Exit (exitFailure, exitSuccess)
main :: IO ()
main = do
counts <- runTestTT $ "Test1" ~: 1 + 1 ~?= 2
if errors counts + failures counts == 0
then exitSuccess
else exitFailure
2025年8月10日日曜日
Haskell入門P286
actionIO action = do
mv <- newEmptyMVar :: IO (MVar (Either SomeException a))
_tid <- forkIO $ do
result <- try acttion
putMVar mv result
result <- takeMVar mv
case result of
Left e -> throwIO e
Right r -> return
2025年8月9日土曜日
Haskell入門 P285 MVarによるスレッド間の通信
ChatGPTもlevel5になって、さらにバージョンアップした感じです。
本を読んでも、なかなか理解しにくかったところも、ChatGPTにコードを解説してもらうとすぐに理解できたので、質問者のレベルに合わせて説明できる能力に驚いています。
2025年7月2日水曜日
今年から市民農園再開
しばらくやめていた市民農園に再挑戦で、今年は小玉スイカの空中栽培も試してみた。植え付け時は、炭疽病を心配し、乗り越えたかと思えば、今度はウリハムシ、そして受粉がなかなかうまくいかないとか、いろいろありましたが、今のところ、それほど雨に悩まされることなく病気の症状もおさまっているようです。このまま梅雨明けしてくれるといいのですが。
2025年6月26日木曜日
ロープの結び方
畑作業でもよく使うので、男結び等について 図にまとめてみました。(トラックロープの結び方は南京結びともいうようです。) 他にも、巻き結び、もやい結び、結束結び、自在結び、ひとえつぎ結び等、覚えておくと便利なようです。
GASではJSON.stringfyをつかったほうがいいようです
畑の収穫記録をGASで管理(収穫の個数を記録しその都度、合計の確認)しようかと、ChatGPTにコード頼んでみたけど、なかなか一筋縄ではいかない。AIにより、だいぶコーディングは楽になっているが、やはり、ある程度やりとりしながら、人間側が修正してあげないと動かなかった。
最初、ChatGPTはサーバ(GAS)からのレスポンスデータを単純にオブジェクトで渡すコードを提示してくれたけれど、それではうまくいかず、やはり、JSON.stringfyを使わないとだめだった。







