Servant API の変遷
HasServer
のroute関数の変遷
class HasServer layout where type ServerT layout (m :: * -> *) :: * route :: *********
version | implementation |
---|---|
0.2.1–0.4.0 | route :: Proxy layout -> Server layout -> RoutingApplication |
0.5–0.6 | route :: Proxy layout -> Context context -> Delayed (Server layout) -> Router |
0.7–0.10 | route :: Proxy api -> Context context -> Delayed env (Server api) -> Router env |
Haskellの名前空間をまとめる実装
下記のようなコードがありVertex3
のドキュメントを確認しようとおもったのですが、上手くドキュメントが見つけられませんでした。
import Graphics.Rendering.OpenGL as GL GL.vertex $ (GL.Vertex3 (-1) (-1) 0 :: GL.Vertex3 GL.GLfloat)
Graphics.Rendering.OpenGL
のページをみてもVertex3
は存在しません。
しかし、ghci
にて確認すると、Graphics.Rendering.OpenGL
に存在するようにみえます。
*Main> :i Graphics.Rendering.OpenGL.Vertex3 data Vertex3 a = Vertex3 !a !a !a -- Defined in ‘Graphics.Rendering.OpenGL.GL.Tensor’ instance [safe] Bounded a => Bounded (Vertex3 a) -- Defined in ‘Graphics.Rendering.OpenGL.GL.Tensor’ instance [safe] Eq a => Eq (Vertex3 a) -- Defined in ‘Graphics.Rendering.OpenGL.GL.Tensor’ instance [safe] Functor Vertex3 -- Defined in ‘Graphics.Rendering.OpenGL.GL.Tensor’ instance [safe] Ord a => Ord (Vertex3 a) -- Defined in ‘Graphics.Rendering.OpenGL.GL.Tensor’ instance [safe] Read a => Read (Vertex3 a) -- Defined in ‘Graphics.Rendering.OpenGL.GL.Tensor’ instance [safe] Show a => Show (Vertex3 a) -- Defined in ‘Graphics.Rendering.OpenGL.GL.Tensor’ instance [safe] Applicative Vertex3 -- Defined in ‘Graphics.Rendering.OpenGL.GL.Tensor’ instance [safe] Foldable Vertex3 -- Defined in ‘Graphics.Rendering.OpenGL.GL.Tensor’ instance [safe] Traversable Vertex3 -- Defined in ‘Graphics.Rendering.OpenGL.GL.Tensor’ instance TrimmingPoint Vertex3 -- Defined in ‘Graphics.Rendering.OpenGL.GLU.NURBS’ instance VertexAttribComponent a => VertexAttrib (Vertex3 a) -- Defined in ‘Graphics.Rendering.OpenGL.GL.VertexSpec’ instance VertexComponent a => Vertex (Vertex3 a) -- Defined in ‘Graphics.Rendering.OpenGL.GL.VertexSpec’ instance UniformComponent a => Uniform (Vertex3 a) -- Defined in ‘Graphics.Rendering.OpenGL.GL.Shaders.Uniform’ instance WindowPosComponent a => WindowPos (Vertex3 a) -- Defined in ‘Graphics.Rendering.OpenGL.GL.RasterPos’ instance RasterPosComponent a => RasterPos (Vertex3 a) -- Defined in ‘Graphics.Rendering.OpenGL.GL.RasterPos’ instance ControlPoint Vertex3 -- Defined in ‘OpenGL-3.0.1.0:Graphics.Rendering.OpenGL.GL.ControlPoint’ *Main>
よく読むと、-- Defined in ‘Graphics.Rendering.OpenGL.GL.Tensor’
とあるので、実際はTensor
パッケージに存在しているようです。ghci
で確認すると、確かにあるようです。
*Main> :i Graphics.Rendering.OpenGL.GL.Tensor.Vertex3 data Vertex3 a = Vertex3 !a !a !a -- Defined in ‘Graphics.Rendering.OpenGL.GL.Tensor’ instance [safe] Bounded a => Bounded (Vertex3 a) -- Defined in ‘Graphics.Rendering.OpenGL.GL.Tensor’ instance [safe] Eq a => Eq (Vertex3 a) -- Defined in ‘Graphics.Rendering.OpenGL.GL.Tensor’ instance [safe] Functor Vertex3 -- Defined in ‘Graphics.Rendering.OpenGL.GL.Tensor’ instance [safe] Ord a => Ord (Vertex3 a) -- Defined in ‘Graphics.Rendering.OpenGL.GL.Tensor’ instance [safe] Read a => Read (Vertex3 a) -- Defined in ‘Graphics.Rendering.OpenGL.GL.Tensor’ instance [safe] Show a => Show (Vertex3 a) -- Defined in ‘Graphics.Rendering.OpenGL.GL.Tensor’ instance [safe] Applicative Vertex3 -- Defined in ‘Graphics.Rendering.OpenGL.GL.Tensor’ instance [safe] Foldable Vertex3 -- Defined in ‘Graphics.Rendering.OpenGL.GL.Tensor’ instance [safe] Traversable Vertex3 -- Defined in ‘Graphics.Rendering.OpenGL.GL.Tensor’ instance TrimmingPoint Vertex3 -- Defined in ‘Graphics.Rendering.OpenGL.GLU.NURBS’ instance VertexAttribComponent a => VertexAttrib (Vertex3 a) -- Defined in ‘Graphics.Rendering.OpenGL.GL.VertexSpec’ instance VertexComponent a => Vertex (Vertex3 a) -- Defined in ‘Graphics.Rendering.OpenGL.GL.VertexSpec’ instance UniformComponent a => Uniform (Vertex3 a) -- Defined in ‘Graphics.Rendering.OpenGL.GL.Shaders.Uniform’ instance WindowPosComponent a => WindowPos (Vertex3 a) -- Defined in ‘Graphics.Rendering.OpenGL.GL.RasterPos’ instance RasterPosComponent a => RasterPos (Vertex3 a) -- Defined in ‘Graphics.Rendering.OpenGL.GL.RasterPos’ instance ControlPoint Vertex3 -- Defined in ‘OpenGL-3.0.1.0:Graphics.Rendering.OpenGL.GL.ControlPoint’ *Main>
不思議に思いソースコードを確認したところ、名前空間をまとめているようです。
https://github.com/haskell-opengl/OpenGL/blob/master/src/Graphics/Rendering/OpenGL.hs
module Graphics.Rendering.OpenGL ( ... module Graphics.Rendering.OpenGL.GL , module Graphics.Rendering.OpenGL.GLU ... ) where
https://github.com/haskell-opengl/OpenGL/blob/master/src/Graphics/Rendering/OpenGL/GL.hs
module Graphics.Rendering.OpenGL.GL ( ... module Graphics.Rendering.OpenGL.GL.Tensor, ... ) where
https://github.com/haskell-opengl/OpenGL/blob/master/src/Graphics/Rendering/OpenGL/GL/Tensor.hs
module Graphics.Rendering.OpenGL.GL.Tensor ( Vertex1(..), Vertex2(..), Vertex3(..), Vertex4(..), Vector1(..), Vector2(..), Vector3(..), Vector4(..) ) where
Java
でいうimport foo.bar.*
のようなワイルドカードを使ってインポートする機能がhaskell
にはないためなのでしょうか。ワイルドカードをつかうと曖昧になるので機能としてないみたいです。
ServantのAPIからHandlerへの型の流れを確認する
Servant
のチュートリアルでは、2.2.3でチートシートのように説明されています。
https://media.readthedocs.org/pdf/haskell-servant/v0.6/haskell-servant.pdf
combinator | handelrのパラメータ | 補足 |
---|---|---|
Capture “something” a | a | |
QueryParam “something” a | Maybe a | |
Header “something” a | Maybe a | |
QueryFlag “something” | Bool | |
QueryParams “something” | [a] | |
ReqBody contentTypes a | a | |
Delete, Get, Patch, Post, Put | ExceptT ServantErr IO |
これはハンドラそのも |
この点の理解ができていなかったので、ServantでHandlerのパラメータどのように作られるか型を辿って確認してみました。
ポイントはtype family
で指定される型の対応を地道に辿っていくことです。
Learn Physics の導入
Learn Physics
learn-physics: Haskell code for learning physics
stack
でインストールしてみます。
bar:graphics foo$ stack new graphics-work01 Downloading template "new-template" to create project "graphics-work01" in graphics-work01/ ... The following parameters were needed by the template but not provided: author-email, author-name, category, copyright, github-username You can provide them in /Users/foo/.stack/config.yaml, like this: templates: params: author-email: value author-name: value category: value copyright: value github-username: value Or you can pass each one as parameters like this: stack new graphics-work01 new-template -p "author-email:value" -p "author-name:value" -p "category:value" -p "copyright:value" -p "github-username:value" Looking for .cabal or package.yaml files to use to init the project. Using cabal packages: - graphics-work01/graphics-work01.cabal Selecting the best among 10 snapshots... Downloaded lts-8.11 build plan. Fetching package index ...remote: Counting objects: 6105, done. remote: Compressing objects: 100% (4824/4824), done. remote: Total 6105 (delta 1641), reused 5005 (delta 1120), pack-reused 0 Receiving objects: 100% (6105/6105), 1.80 MiB | 2.27 MiB/s, done. Resolving deltas: 100% (1641/1641), completed with 677 local objects. From https://github.com/commercialhaskell/all-cabal-hashes + 94fd2e6...dbe78f6 hackage -> origin/hackage (forced update) - [tag update] current-hackage -> current-hackage Fetched package index. Populated index cache. Did not find .cabal file for unbounded-delays-0.1.0.10 with Git SHA of f02d37e48a454a6d91bbc9106222ea7fdd7764d2 Right Nothing * Matches lts-8.11 Selected resolver: lts-8.11 Initialising configuration using resolver: lts-8.11 Total number of user packages considered: 1 Writing configuration to file: graphics-work01/stack.yaml All done.
Cabalの編集
executable graphics-work01-exe hs-source-dirs: app main-is: Main.hs ghc-options: -threaded -rtsopts -with-rtsopts=-N build-depends: base , graphics-work01 , learn-physics
stack.yamlの編集をします。
# Dependency packages to be pulled from upstream that are not in the resolver # (e.g., acme-missiles-0.3) extra-deps: [ learn-physics-0.6.0.2 , not-gloss-0.7.7.0 , spatial-math-0.2.7.0 ]
上記のstack.yamlの設定をしないでstack build
すると、エラーとなります。
bar:graphics-work01 foo$ stack build While constructing the BuildPlan the following exceptions were encountered: -- Failure when adding dependencies: learn-physics: needed (-any), stack configuration has no specified version (latest applicable is 0.6.0.2) needed for package graphics-work01-0.1.0.0 -- While attempting to add dependency, Could not find package learn-physics in known packages Recommended action: try adding the following to your extra-deps in /Users/foo/work03/graphics/graphics-work01/stack.yaml - learn-physics-0.6.0.2 You may also want to try the 'stack solver' command
このエラーを解決するにはstack solver
を実行します。そうすると、修正方法を教えてくれます。これが上述の設定になります。
bar:graphics-work01 foo$ stack solver Using configuration file: stack.yaml Using cabal packages: - graphics-work01.cabal Using resolver: lts-8.11 Using compiler: ghc-8.0.2 Asking cabal to calculate a build plan... Trying with packages from lts-8.11 as hard constraints... Successfully determined a build plan with 3 external dependencies. The following changes will be made to stack.yaml: * Resolver is lts-8.11 * Dependencies to be added extra-deps: - learn-physics-0.6.0.2 - not-gloss-0.7.7.0 - spatial-math-0.2.7.0 To automatically update stack.yaml, rerun with '--update-config'
初回のstack build
で依存関係を解決したライブラリがインストールされます。
bar:graphics-work01 foo$ stack build graphics-work01-0.1.0.0: unregistering (missing dependencies: learn-physics) ObjectName-1.1.0.1: download ObjectName-1.1.0.1: configure 途中省略[f:id:naotoogawa:20170416134218p:plain] learn-physics-0.6.0.2: build learn-physics-0.6.0.2: copy/register graphics-work01-0.1.0.0: configure Configuring graphics-work01-0.1.0.0... graphics-work01-0.1.0.0: build Preprocessing library graphics-work01-0.1.0.0... [1 of 1] Compiling Lib ( src/Lib.hs, .stack-work/dist/x86_64-osx/Cabal-1.24.2.0/build/Lib.o ) ld: warning: directory not found for option '-L/opt/local/lib/' Preprocessing executable 'graphics-work01-exe' for graphics-work01-0.1.0.0... [1 of 1] Compiling Main ( app/Main.hs, .stack-work/dist/x86_64-osx/Cabal-1.24.2.0/build/graphics-work01-exe/graphics-work01-exe-tmp/Main.o ) [Lib changed] Linking .stack-work/dist/x86_64-osx/Cabal-1.24.2.0/build/graphics-work01-exe/graphics-work01-exe ... ld: warning: directory not found for option '-L/opt/local/lib/' graphics-work01-0.1.0.0: copy/register Installing library in /Users/foo/work03/graphics/graphics-work01/.stack-work/install/x86_64-osx/lts-8.11/8.0.2/lib/x86_64-osx-ghc-8.0.2/graphics-work01-0.1.0.0-Df1PA4o0N7R3GcxbM23sV6 Installing executable(s) in /Users/foo/work03/graphics/graphics-work01/.stack-work/install/x86_64-osx/lts-8.11/8.0.2/bin Registering graphics-work01-0.1.0.0... Completed 61 action(s). bar:graphics-work01 foo$ ls
サンプルを取得します。
bar:app foo$ curl -O https://raw.githubusercontent.com/walck/learn-physics/master/examples/src/LorentzForceSimulation.hs % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 1464 100 1464 0 0 4636 0 --:--:-- --:--:-- --:--:-- 4647 bar:app foo$ ls LorentzForceSimulation.hs Main.hs eFieldLine2D.hs bar:app foo$
cabal
ファイルに、main
関数があるファイルの指定と、依存関係ライブラリの指定を追加します。
executable graphics-work01-exe hs-source-dirs: app main-is: LorentzFoArceSimulation.hs ghc-options: -threaded -rtsopts -with-rtsopts=-N build-depends: base , graphics-work01 , learn-physics , not-gloss , spatial-math , gloss default-language: Haskell2010
ビルドします。
bar:graphics-work01 foo$ stack build graphics-work01-0.1.0.0: build Preprocessing library graphics-work01-0.1.0.0... Preprocessing executable 'graphics-work01-exe' for graphics-work01-0.1.0.0... [1 of 1] Compiling Main ( app/LorentzForceSimulation.hs, .stack-work/dist/x86_64-osx/Cabal-1.24.2.0/build/graphics-work01-exe/graphics-work01-exe-tmp/Main.o ) Linking .stack-work/dist/x86_64-osx/Cabal-1.24.2.0/build/graphics-work01-exe/graphics-work01-exe ... ld: warning: directory not found for option '-L/opt/local/lib/' graphics-work01-0.1.0.0: copy/register Installing library in /Users/foo/work03/graphics/graphics-work01/.stack-work/install/x86_64-osx/lts-8.11/8.0.2/lib/x86_64-osx-ghc-8.0.2/graphics-work01-0.1.0.0-Jws64xXpAJx1AXCetAcS6y Installing executable(s) in /Users/foo/work03/graphics/graphics-work01/.stack-work/install/x86_64-osx/lts-8.11/8.0.2/bin Registering graphics-work01-0.1.0.0...
実行します。
bar:graphics-work01 foo$ stack exec graphics-work01-exe
bar:graphics-work01 foo$