hgg-ihaskell (empty) → 0.1.0.0
raw patch · 6 files changed
+309/−0 lines, 6 filesdep +basedep +containersdep +hgg-core
Dependencies added: base, containers, hgg-core, hgg-frame, hgg-ihaskell, hgg-svg, ihaskell, text, vector
Files
- CHANGELOG.md +7/−0
- LICENSE +30/−0
- examples/DemoSvg.hs +55/−0
- hgg-ihaskell.cabal +63/−0
- src/Graphics/Hgg/IHaskell.hs +87/−0
- test/Spec.hs +67/−0
+ CHANGELOG.md view
@@ -0,0 +1,7 @@+# Changelog for `hgg-ihaskell`++## 0.1.0.0 — 2026-07-18++First public release on Hackage.++- iHaskell (Jupyter) inline display backend.
+ LICENSE view
@@ -0,0 +1,30 @@+BSD 3-Clause License++Copyright (c) 2026, Toshiaki Honda+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++1. Redistributions of source code must retain the above copyright notice,+ this list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright notice,+ this list of conditions and the following disclaimer in the documentation+ and/or other materials provided with the distribution.++3. Neither the name of the copyright holder nor the names of its+ contributors may be used to endorse or promote products derived from this+ software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE+POSSIBILITY OF SUCH DAMAGE.
+ examples/DemoSvg.hs view
@@ -0,0 +1,55 @@+-- | Phase 12 A4: demo.ipynb の各セルが iHaskell 上で出力するのと同じ SVG を+-- ファイルに書き出す (= notebook の出力を環境非依存に確認するための具体物)。+--+-- @cabal run ihaskell-demo-svg@ → design/ihaskell/ に 3 枚の SVG を生成。+-- iHaskell セルでは @display@ がこの SVG を inline 表示する (= 同一描画経路)。+{-# LANGUAGE OverloadedStrings #-}+module Main (main) where++import Graphics.Hgg.Backend.SVG (renderSVG, renderSVGWith)+import Graphics.Hgg.Easy+import qualified Data.Text.IO as TIO+import qualified Data.Vector as V++outDir :: FilePath+outDir = "design/ihaskell/"++-- セル 1: inline 散布図 (Resolver 不要、 IHaskellDisplay VisualSpec が描く図)+cell1 :: VisualSpec+cell1 =+ layer (scatter (inline xs) (inline ys) <> size 5)+ <> title "Cell 1: inline scatter (y = x²)"+ <> xLabel "x" <> yLabel "y"+ where+ xs = [0, 1 .. 9] :: [Double]+ ys = map (\x -> x * x) xs++-- セル 2: Easy 層 + 折れ線の重畳 (overlay)+cell2 :: VisualSpec+cell2 =+ layer (points xs ys <> size 5)+ <> layer (lineXY xs fitY <> color (fromHex "#d62728") <> stroke 2)+ <> title "Cell 2: Easy points + line overlay"+ where+ xs = [0, 1 .. 9] :: [Double]+ ys = map (\x -> x * x) xs+ fitY = map (\x -> 8 * x - 12) xs++-- セル 3: ColByName 図 + Resolver (DisplayPlot が描く図)+cell3Spec :: VisualSpec+cell3Spec =+ layer (scatter (ColByName "x") (ColByName "y") <> size 5)+ <> title "Cell 3: ColByName + Resolver"+ <> xLabel "x" <> yLabel "y"++cell3Resolver :: Resolver+cell3Resolver "x" = Just (NumData (V.fromList [0, 1, 2, 3, 4]))+cell3Resolver "y" = Just (NumData (V.fromList [3, 1, 4, 1, 5]))+cell3Resolver _ = Nothing++main :: IO ()+main = do+ TIO.writeFile (outDir ++ "cell1-inline-scatter.svg") (renderSVG cell1)+ TIO.writeFile (outDir ++ "cell2-easy-overlay.svg") (renderSVG cell2)+ TIO.writeFile (outDir ++ "cell3-colbyname.svg") (renderSVGWith cell3Resolver cell3Spec)+ putStrLn "wrote 3 demo SVGs to design/ihaskell/"
+ hgg-ihaskell.cabal view
@@ -0,0 +1,63 @@+cabal-version: 3.0+name: hgg-ihaskell+version: 0.1.0.0+extra-doc-files: CHANGELOG.md+synopsis: iHaskell (Jupyter) inline display backend for hgg+description:+ A thin wiring package that displays hgg figures inline in Jupyter+ cells running the IHaskell kernel. It simply passes the Text returned+ by the SVG backend ('renderSVG') to IHaskell's SVG display. The+ @ihaskell@ dependency is isolated here, keeping hgg-core / hgg-svg+ dependency-clean.+license: BSD-3-Clause+homepage: https://github.com/frenzieddoll/hgg+license-file: LICENSE+author: Toshiaki Honda+maintainer: frenzieddoll@gmail.com+copyright: 2026 Aelysce Project (Toshiaki Honda)+category: Graphics+build-type: Simple++common warnings+ ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates+ -Wincomplete-uni-patterns -Wpartial-fields+ -Wredundant-constraints++library+ import: warnings+ exposed-modules: Graphics.Hgg.IHaskell+ hs-source-dirs: src+ build-depends: base >= 4.17 && < 5+ , text >= 2.0 && < 2.2+ , ihaskell >= 0.11 && < 0.14+ , hgg-core ^>= 0.1+ , hgg-frame ^>= 0.1+ , hgg-svg ^>= 0.1+ default-language: Haskell2010++-- Writes out the SVGs produced by each cell of design/ihaskell/demo.ipynb (for output verification)+executable ihaskell-demo-svg+ import: warnings+ main-is: DemoSvg.hs+ hs-source-dirs: examples+ build-depends: base >= 4.17 && < 5+ , text+ , vector+ , hgg-core+ , hgg-svg+ default-language: Haskell2010++test-suite hgg-ihaskell-tests+ import: warnings+ type: exitcode-stdio-1.0+ main-is: Spec.hs+ hs-source-dirs: test+ build-depends: base >= 4.17 && < 5+ , text+ , vector+ , containers+ , ihaskell+ , hgg-core+ , hgg-frame+ , hgg-ihaskell+ default-language: Haskell2010
+ src/Graphics/Hgg/IHaskell.hs view
@@ -0,0 +1,87 @@+-- |+-- Module : Graphics.Hgg.IHaskell+-- Description : iHaskell (Jupyter) inline display 配線 (Phase 12)+-- Copyright : (c) 2026 Aelysce Project (Toshiaki Honda)+-- License : BSD-3-Clause+--+-- Jupyter (iHaskell kernel) のセルで hgg の図をインライン描画する+-- ための薄い配線。 描画は SVG backend の純関数 'renderSVG' をそのまま使い、+-- iHaskell の 'svg' display helper に 'Text' を渡すだけ (新規描画コード無し)。+--+-- == 使い方 (Jupyter セル)+--+-- @+-- import Graphics.Hgg.Easy+-- import Graphics.Hgg.IHaskell () -- インスタンスを見せるだけで良い+--+-- layer (points [0,1,2,3] [0,1,4,9]) <> title \"demo\" -- ← セル評価でインライン描画+-- @+--+-- 'ColByName' を含む図 (= Resolver 必須) は 'BoundPlot' (@df |>> spec@) を使う。+-- 旧 'DisplayPlot' は Phase 14 で 'BoundPlot' に統合され deprecated。++-- orphan instance を意図的に許可: 'IHaskellDisplay' (ihaskell) を 'VisualSpec' /+-- 'BoundPlot' (core / frame) に与えるのは、 ihaskell 依存を本 package に隔離する+-- 設計上必須。+{-# OPTIONS_GHC -Wno-orphans #-}+module Graphics.Hgg.IHaskell+ ( -- * df バインド済図 (= 'ColByName' を含む図、 Phase 14 で正規化)+ BoundPlot (..)+ -- * 旧 Resolver 同伴図 (deprecated → 'BoundPlot' へ)+ , DisplayPlot (..)+ -- * 明示 helper (インスタンスに頼らず関数で出す場合)+ , displaySVG+ ) where++import Graphics.Hgg.Backend.SVG (renderSVG, renderSVGWith)+import Graphics.Hgg.Frame (BoundPlot (..))+import Graphics.Hgg.Spec (Resolver, VisualSpec)+import IHaskell.Display (Display (..), IHaskellDisplay (..),+ svg)++-- ============================================================================+-- inline 図 (Resolver 不要 = Easy 層 / tutorial 系)+-- ============================================================================++-- | inline 列のみで構成された図 ('ColByName' を含まない) をセル評価値として+-- 直接インライン描画する。 'renderSVG' に 'emptyResolver' を渡す。+--+-- orphan instance (型は core、 class は ihaskell) だが、 ihaskell 表示配線は+-- 本 package に隔離する設計上意図的なもの。+instance IHaskellDisplay VisualSpec where+ display spec = pure (Display [svg (renderSVG spec)])++-- ============================================================================+-- df バインド済図 (= ColByName を含む図、 Phase 14 で正規化)+-- ============================================================================++-- | 'BoundPlot' (= @df |>> spec@ の結果) をセル評価値として描画する。+-- 'bpResolver' で 'ColByName' を解決し 'renderSVG' で SVG 化する。+-- 検証診断 ('bpDiagnostics') はインライン表示では無視する (Jupyter の stderr+-- には出ない経路ゆえ。 必要なら利用者が 'bpDiagnostics' を直接見る)。+instance IHaskellDisplay BoundPlot where+ display (BoundPlot r spec _) = pure (Display [svg (renderSVGWith r spec)])++-- ============================================================================+-- 旧 Resolver 同伴図 (deprecated → BoundPlot)+-- ============================================================================++-- | 'Resolver' と 'VisualSpec' を束ねた表示用 newtype。+--+-- __Deprecated__: Phase 14 で 'BoundPlot' (@df |>> spec@) に統合された。+-- 新規コードは 'BoundPlot' を使うこと。 当面は前方互換のため併存する。+newtype DisplayPlot = DisplayPlot (Resolver, VisualSpec)+{-# DEPRECATED DisplayPlot+ "Phase 14 で BoundPlot (Graphics.Hgg.Frame、 df |>> spec) に統合されました。 BoundPlot を使ってください。" #-}++instance IHaskellDisplay DisplayPlot where+ display (DisplayPlot (r, spec)) = pure (Display [svg (renderSVGWith r spec)])++-- ============================================================================+-- 明示 helper+-- ============================================================================++-- | 'Resolver' を明示して図を 'Display' にする。 inline 図なら+-- @displaySVG emptyResolver spec@、 'ColByName' を含む図なら実 resolver を渡す。+displaySVG :: Resolver -> VisualSpec -> Display+displaySVG r spec = Display [svg (renderSVGWith r spec)]
+ test/Spec.hs view
@@ -0,0 +1,67 @@+-- | Phase 12 iHaskell backend の単体 test。+-- ghci 相当の確認: 'display' が SVG を含む 'Display' を返すこと。+-- DisplayPlot は Phase 14 で deprecated だが後方互換確認のため残す → 警告抑制。+{-# LANGUAGE OverloadedStrings #-}+{-# OPTIONS_GHC -Wno-deprecations #-}+module Main (main) where++import Graphics.Hgg.Easy (layer, points, scatter, title)+import Graphics.Hgg.Frame (BoundPlot, (|>>))+import Graphics.Hgg.IHaskell (DisplayPlot (..))+import Graphics.Hgg.Spec (ColData (..), ColRef (..), Resolver,+ VisualSpec)+import Control.Monad (unless)+import Data.Map.Strict (Map)+import qualified Data.Map.Strict as M+import Data.Text (Text)+import qualified Data.Vector as V+import IHaskell.Display (Display (..), display)+import System.Exit (exitFailure)++-- inline 列のみの図 (Resolver 不要)+demoSpec :: VisualSpec+demoSpec = layer (points [0, 1, 2, 3] [0, 1, 4, 9]) <> title "demo"++-- ColByName を含む図 (= Resolver 必須)+namedSpec :: VisualSpec+namedSpec = layer (scatter (ColByName "x") (ColByName "y")) <> title "named"++-- 列名 → 実 Vector を返す Resolver+demoResolver :: Resolver+demoResolver "x" = Just (NumData (V.fromList [0, 1, 2, 3]))+demoResolver "y" = Just (NumData (V.fromList [0, 1, 4, 9]))+demoResolver _ = Nothing++-- df (Map) → BoundPlot (Phase 14 A6 の正規ルート)+demoDF :: Map Text ColData+demoDF = M.fromList+ [ ("x", NumData (V.fromList [0, 1, 2, 3]))+ , ("y", NumData (V.fromList [0, 1, 4, 9])) ]++boundPlot :: BoundPlot+boundPlot = demoDF |>> (layer (scatter (ColByName "x") (ColByName "y")) <> title "bound")++displayLen :: Display -> Int+displayLen (Display ds) = length ds+displayLen (ManyDisplay _) = -1++main :: IO ()+main = do+ -- A2 完了条件: inline 図 display が Display [<one DisplayData>] を返す+ dInline <- display demoSpec+ check "inline: display returns Display with one DisplayData"+ (displayLen dInline == 1)+ -- Phase 14 A6: BoundPlot (df |>> spec) を display できる (正規ルート)+ dBound <- display boundPlot+ check "bound: BoundPlot display returns Display with one DisplayData"+ (displayLen dBound == 1)+ -- 後方互換: 旧 DisplayPlot も依然 display できる (deprecated だが機能維持)+ dNamed <- display (DisplayPlot (demoResolver, namedSpec))+ check "named: DisplayPlot (deprecated) display still returns one DisplayData"+ (displayLen dNamed == 1)+ putStrLn "hgg-ihaskell: all tests passed"++check :: String -> Bool -> IO ()+check label ok = unless ok $ do+ putStrLn ("FAIL: " ++ label)+ exitFailure