feat(claude): claude-codeのpluginを作成#113
Conversation
まだHimari内部のドキュメントと外部向けのガイドラインが整備されていないため、 準備はまだ完了していません。 言語拡張などは内部と外部推奨を同じにすることを検討します。
PR #113 レビュー: Claude Code Plugin作成概要このPRはClaude Code用のpluginを新規作成し、HimariカスタムPreludeを使ったHaskellプロジェクトの開発支援を行うものです。全体として良い構成になっています。 👍 良い点
🔧 改善提案1. coding-style.md: 禁止言語拡張リストの差異CLAUDE.mdでは禁止されているが、coding-style.mdには記載がない言語拡張:
逆にcoding-style.mdにあるがCLAUDE.mdにない言語拡張:
提案: 両者を完全に一致させるか、coding-style.mdにはCLAUDE.mdへの参照を明記するのが良いでしょう。 2. coding-style.md: 部分関数の追加例CLAUDE.mdでは 3. examples.md: 存在しない関数の使用processInParallel :: MonadUnliftIO m => [Item] -> m [Result]
processInParallel items =
withTaskGroup 4 $ \group -> do
asyncs <- forM items $ \item ->
async group (processItem item)
mapM wait asyncs
実際のunliftio/asyncで書く場合: processInParallel :: MonadUnliftIO m => [Item] -> m [Result]
processInParallel items =
pooledMapConcurrentlyN 4 processItem itemsもしくは: processInParallel :: MonadUnliftIO m => [Item] -> m [Result]
processInParallel = mapConcurrently processItem4. SKILL.md: 軽微な誤り禁止言語拡張のセクションで 5. plugin.json: 軽微な確認
💡 追加の提案
📋 総評全体的に良いPRです。CLAUDE.mdの重要なルールがpluginに反映されており、Claude Codeがhimariプロジェクトの規約に従ったコードを生成するのに役立つでしょう。 上記の軽微な改善点を検討いただければ、さらに良くなると思います。 |
There was a problem hiding this comment.
Pull request overview
このPRはissue #64に対応し、Claude Code用のhimariプラグインを作成しています。himariはrioの代替となるカスタムPreludeライブラリで、このプラグインはClaude CodeでHaskellコードを書く際にhimariのベストプラクティスとコーディング規約をガイドする目的で作られています。
Changes:
- Claude Codeプラグインのメタデータファイル(
.claude-plugin/plugin.json)を追加 - himariスキルの主要ドキュメント(
SKILL.md)を作成し、基本的な使用方法と禁止事項を記載 - 詳細なコーディングスタイルガイド(
coding-style.md)を作成し、言語拡張、関数の使用制限、エラーハンドリング等を網羅 - 具体的な使用例(
examples.md)を追加し、リソース管理パターンを示す
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 7 comments.
| File | Description |
|---|---|
.claude-plugin/plugin.json |
Claude Codeプラグインのメタデータを定義(名前、説明、バージョン、作者、リポジトリ情報) |
skills/himari/SKILL.md |
himariの基本的な使い方と主要な禁止事項を簡潔にまとめたスキル定義ファイル |
skills/himari/coding-style.md |
himariを使用したHaskell開発における詳細なコーディング規約とベストプラクティス |
skills/himari/examples.md |
bracketパターンやwithパターンを使用したリソース管理の具体的な使用例 |
| ```haskell | ||
| -- 禁止 | ||
| calculate :: Int -> Int | ||
| calculate x | ||
| | x < 0 = error "negative input" | ||
| | otherwise = x * 2 | ||
|
|
||
| -- 推奨: Either/Maybeを返す | ||
| calculate :: Int -> Either CalculationError Int | ||
| calculate x | ||
| | x < 0 = Left NegativeInput | ||
| | otherwise = Right (x * 2) | ||
|
|
||
| -- 推奨: MonadThrowを使用 | ||
| calculate :: MonadThrow m => Int -> m Int | ||
| calculate x | ||
| | x < 0 = throwM NegativeInputException | ||
| | otherwise = pure (x * 2) | ||
| ``` |
There was a problem hiding this comment.
コード例に型定義が不完全です。CalculationError型とNegativeInputException型が使用されていますが、定義されていません。例として完全性を持たせるため、以下のような定義を追加することを推奨します:
data CalculationError = NegativeInputまたは
data NegativeInputException = NegativeInputException
deriving stock (Show)
deriving anyclass (Exception)| ```haskell | ||
| data User = User | ||
| { name :: Text | ||
| , email :: Text | ||
| } | ||
|
|
||
| makeFieldsId ''User | ||
| -- フィールドにプレフィクスやアンダースコアは不要 | ||
| ``` |
There was a problem hiding this comment.
Template HaskellのLANGUAGEプラグマが記載されていません。makeFieldsIdを使用する際はTemplateHaskell拡張が必要です。コード例に以下を追加してください:
{-# LANGUAGE TemplateHaskell #-}これはcoding-style.mdの185-202行目の例では正しく記載されています。
| - `read` - 部分関数、代わりに`readMaybe`を使用 | ||
| - `unsafePerformIO`系全般 | ||
|
|
There was a problem hiding this comment.
部分関数のリストが不完全です。coding-style.mdではhead, tail, (!!)も禁止されていますが、SKILL.mdには記載されていません。一貫性のため、全ての禁止されている部分関数をリストアップするか、または詳細はcoding-style.mdを参照するように記載してください。
| - `read` - 部分関数、代わりに`readMaybe`を使用 | |
| - `unsafePerformIO`系全般 | |
| - `read` - 部分関数、代わりに`readMaybe`を使用 | |
| - `head` - 部分関数 | |
| - `tail` - 部分関数 | |
| - `(!!)` - 部分関数 | |
| - `unsafePerformIO`系全般 | |
| ※ 他の禁止されている部分関数や詳細な理由については `coding-style.md` を参照してください。 |
| - `ImplicitParams` | ||
| - `IncoherentInstances` | ||
| - `OverlappingInstances` |
There was a problem hiding this comment.
危険な言語拡張のリストが不完全です。以下の言語拡張も禁止事項に含める必要があります:
ImpredicativeTypesLiberalTypeSynonymsRebindableSyntax
これらの拡張はcoding-style.mdと内部ガイドラインには記載されていますが、こちらには含まれていません。一貫性のため、全ての禁止されている言語拡張をリストアップするか、または詳細はcoding-style.mdを参照するように記載してください。
| - `ImplicitParams` | |
| - `IncoherentInstances` | |
| - `OverlappingInstances` | |
| - `ImplicitParams` | |
| - `ImpredicativeTypes` | |
| - `IncoherentInstances` | |
| - `LiberalTypeSynonyms` | |
| - `OverlappingInstances` | |
| - `RebindableSyntax` |
| -- 推奨: 例外を使用 | ||
| fetchUser :: IO User -- 失敗時は例外 | ||
|
|
||
| -- ただしlookup操作は例外 |
There was a problem hiding this comment.
誤字があります。「ただしlookup操作は例外」は文脈から「ただしlookup操作は例外ではない」または「ただしlookup操作は除外」の意味だと思われます。「例外」という言葉が二重の意味で使われているため、「存在しないのは正常系」という説明から推測すると、ここは「ただしlookup操作は例外的なケース」または「ただしlookup操作は除く」と書くべきです。
| -- ただしlookup操作は例外 | |
| -- ただしlookup操作は除く |
| ```haskell | ||
| module MyApp.Database | ||
| ( withConnection | ||
| , runQuery | ||
| ) where | ||
|
|
||
| import Himari | ||
|
|
||
| withConnection :: MonadUnliftIO m => ConnectionString -> (Connection -> m a) -> m a | ||
| withConnection connStr action = | ||
| bracket | ||
| (liftIO $ connect connStr) | ||
| (liftIO . close) | ||
| action | ||
|
|
||
| runQuery :: MonadUnliftIO m => ConnectionString -> Query -> m [Row] | ||
| runQuery connStr query = | ||
| withConnection connStr $ \conn -> | ||
| liftIO $ execute conn query | ||
| ``` |
There was a problem hiding this comment.
コード例が不完全です。以下の型や関数が定義されていないため、このコードはコンパイルできません:
ConnectionStringConnectionQueryRowconnectcloseexecute
実際の使用例として完全性を持たせるために、これらの型や関数を定義するか、または「疑似コード」であることを明示してください。または、実際のライブラリ(例:postgresql-simple)を使用した完全な例を提供することを検討してください。
| ```haskell | ||
| module MyApp.Concurrent | ||
| ( processInParallel | ||
| ) where | ||
|
|
||
| import Himari | ||
|
|
||
| processInParallel :: MonadUnliftIO m => [Item] -> m [Result] | ||
| processInParallel items = | ||
| withTaskGroup 4 $ \group -> do | ||
| asyncs <- forM items $ \item -> | ||
| async group (processItem item) | ||
| mapM wait asyncs | ||
| ``` |
There was a problem hiding this comment.
コード例が不完全です。以下の型や関数が定義されていないため、このコードはコンパイルできません:
ItemResultwithTaskGroupasync(groupを引数に取るバージョン)processItemwait
実際の使用例として完全性を持たせるために、これらの型や関数を定義するか、または「疑似コード」であることを明示してください。または、実際の並行処理ライブラリを使用した完全な例を提供することを検討してください。
close #64