msys2 をアップデートしたら、 tmux
でクリップボード周りを操作すると [lost server]
的なメッセージが出て死ぬようになってしまった。今までも何度かあったこととは言え、辛さに溢れる。
とりあえずこれの通り msys2 のランタイムのバージョン下げたら直った。この辺もいつもの通りの対処法。
https://github.com/Alexpux/MSYS2-packages/issues/791#issuecomment-275253779
msys2 をアップデートしたら、 tmux
でクリップボード周りを操作すると [lost server]
的なメッセージが出て死ぬようになってしまった。今までも何度かあったこととは言え、辛さに溢れる。
とりあえずこれの通り msys2 のランタイムのバージョン下げたら直った。この辺もいつもの通りの対処法。
https://github.com/Alexpux/MSYS2-packages/issues/791#issuecomment-275253779
当然のことながら、msys2のshellではなくmingw64のshellから操作する。
まず、 sqlite3 を入れる。
pacman -S mingw64/mingw-w64-x86_64-sqlite3
後はビルドするだけなんだけど、2点注意がいる。
--extra-include-dirs
と --extra-lib-dirs
にmingw64関連のディレクトリを明示する--skip-msys
を指定する--skip-msys
は ここ とか ここ 読めばわかるけど、指定しなければwin環境のGHCがデフォルトで内部に持ってるmsys2のPATHを見てしまうのを、抑制して見ないようにしてくれる。
stack build --skip-msys --extra-include-dirs=/c/msys64/mingw64/include/ --extra-lib-dirs=/c/msys64/mingw64/lib/ HDBC-sqlite3
--extra-*
の指定が必要な理由はよくわからない。明示しなくてもmingw64のshellを使ってるのだから勝手に見て欲しいもの。
依存ライブラリのチェックはcabal側でやってて 、ここで使うgccがどれなのかがまず重要である。ここに関しては一応 stack 側で --with-gcc=/c/msys64/mingw64/bin/gcc
のような指定は可能で、これを指定するとライブラリのチェックでは落ちなくなる。しかし、結局buildの部分で落ちる。
2017-01-29 10:45:52.197846: [debug] Run process: C:\stack_root\setup-exe-cache\x86_64-windows\Cabal-simple_mPHDZzAJ_1.24.2.0_ghc-8.0.1.exe --builddir=.stack-work\dist\ca59d0ab build --ghc-options " -ddump-hi -ddump-to-file" @(System\Process\Read.hs:340:3) -- While building package HDBC-sqlite3-2.3.3.1 using: C:\stack_root\setup-exe-cache\x86_64-windows\Cabal-simple_mPHDZzAJ_1.24.2.0_ghc-8.0.1.exe --builddir=.stack-work\dist\ca59d0ab build --ghc-options " -ddump-hi -ddump-to-file" Process exited with code: ExitFailure 1 ...略... [7 of 7] Compiling Database.HDBC.Sqlite3 ( Database\HDBC\Sqlite3.hs, .stack-work\dist\ca59d0ab\build\Database\HDBC\Sqlite3.o ) C:\tools\msys64\tmp\stack12828\HDBC-sqlite3-2.3.3.1\hdbc-sqlite3-helper.c:1:21: error: fatal error: sqlite3.h: No such file or directory compilation terminated. `gcc.exe' failed in phase `C Compiler'. (Exit code: 1)
ここで setup.exe 呼ぶのにも --with-gcc
が必要な気がするのだけど、 stack がそれを指定していないように見える。が、面倒なのでこれ以上は追いかけてない。
このように f
を定義して実行したい。
f :: String -> String f = show . read main :: IO () main = putStrLn $ f "True"
エラーが出る。
Prelude> :l test.hs [1 of 1] Compiling Main ( test.hs, interpreted ) test.hs:5:5: error: • Ambiguous type variable ‘a0’ arising from a use of ‘show’ prevents the constraint ‘(Show a0)’ from being solved. Probable fix: use a type annotation to specify what ‘a0’ should be. These potential instances exist: instance Show Ordering -- Defined in ‘GHC.Show’ instance Show Integer -- Defined in ‘GHC.Show’ instance Show a => Show (Maybe a) -- Defined in ‘GHC.Show’ ...plus 22 others ...plus 16 instances involving out-of-scope types (use -fprint-potential-instances to see them all) • In the first argument of ‘(.)’, namely ‘show’ In the expression: show . read In an equation for ‘f’: f = show . read test.hs:5:12: error: • Ambiguous type variable ‘a0’ arising from a use of ‘read’ prevents the constraint ‘(Read a0)’ from being solved. Probable fix: use a type annotation to specify what ‘a0’ should be. These potential instances exist: instance Read Ordering -- Defined in ‘GHC.Read’ instance Read Integer -- Defined in ‘GHC.Read’ instance Read a => Read (Maybe a) -- Defined in ‘GHC.Read’ ...plus 22 others ...plus 7 instances involving out-of-scope types (use -fprint-potential-instances to see them all) • In the second argument of ‘(.)’, namely ‘read’ In the expression: show . read In an equation for ‘f’: f = show . read Failed, modules loaded: none.
show
と read
の対象とする型 a0
がきちんと決まってないのが原因なので、これを f
に対して指定できるようにする。
f :: (Show a, Read a) => String -> String f = (show :: a -> String) . read
再びエラーとなる。
Prelude> :r [1 of 1] Compiling Main ( test.hs, interpreted ) test.hs:4:6: error: • Could not deduce (Read a0) from the context: (Show a, Read a) bound by the type signature for: f :: (Show a, Read a) => String -> String at test.hs:4:6-41 The type variable ‘a0’ is ambiguous • In the ambiguity check for ‘f’ To defer the ambiguity check to use sites, enable AllowAmbiguousTypes In the type signature: f :: (Show a, Read a) => String -> String Failed, modules loaded: none.
a
が Show
と Read
のインスタンスだと言ってる割には、型の本文に a
が登場しないのでこれを決定する方法がない。
AllowAmbiguousTypes
を使うとこのチェックを遅らせられるよと教えてくれているので、有効にする。
が、これまたゴツいエラー。
Prelude> :r [1 of 1] Compiling Main ( test.hs, interpreted ) test.hs:5:6: error: • Could not deduce (Show a2) arising from a use of ‘show’ from the context: (Show a, Read a) bound by the type signature for: f :: (Show a, Read a) => String -> String at test.hs:4:1-41 Possible fix: add (Show a2) to the context of an expression type signature: a2 -> String • In the first argument of ‘(.)’, namely ‘(show :: a -> String)’ In the expression: (show :: a -> String) . read In an equation for ‘f’: f = (show :: a -> String) . read test.hs:5:29: error: • Could not deduce (Read a0) arising from a use of ‘read’ from the context: (Show a, Read a) bound by the type signature for: f :: (Show a, Read a) => String -> String at test.hs:4:1-41 The type variable ‘a0’ is ambiguous These potential instances exist: instance Read Ordering -- Defined in ‘GHC.Read’ instance Read Integer -- Defined in ‘GHC.Read’ instance Read a => Read (Maybe a) -- Defined in ‘GHC.Read’ ...plus 22 others ...plus 7 instances involving out-of-scope types (use -fprint-potential-instances to see them all) • In the second argument of ‘(.)’, namely ‘read’ In the expression: (show :: a -> String) . read In an equation for ‘f’: f = (show :: a -> String) . read Failed, modules loaded: none.
これは show :: a -> String
が暗黙的に show :: forall a. a -> String
と解釈されているのが原因なので、 ScopedTypeVariables
拡張を使う。
{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE ScopedTypeVariables #-} f :: forall a. (Show a, Read a) => String -> String f = (show :: a -> String) . read main :: IO () main = putStrLn $ f "True"
f
の定義についてのエラーはなくなった。後は呼び出し側。
*Main> :r [1 of 1] Compiling Main ( test.hs, interpreted ) test.hs:8:19: error: • Ambiguous type variable ‘a0’ arising from a use of ‘f’ prevents the constraint ‘(Read a0)’ from being solved. Probable fix: use a type annotation to specify what ‘a0’ should be. These potential instances exist: instance Read Ordering -- Defined in ‘GHC.Read’ instance Read Integer -- Defined in ‘GHC.Read’ instance Read a => Read (Maybe a) -- Defined in ‘GHC.Read’ ...plus 22 others ...plus 7 instances involving out-of-scope types (use -fprint-potential-instances to see them all) • In the second argument of ‘($)’, namely ‘f "True"’ In the expression: putStrLn $ f "True" In an equation for ‘main’: main = putStrLn $ f "True" Failed, modules loaded: none.
型 a
を指定すればいいのだから、ここで TypeApplications
の登場。
{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} f :: forall a. (Show a, Read a) => String -> String f = (show :: a -> String) . read main :: IO () main = putStrLn $ f @Bool "True"
Prelude> :r [1 of 1] Compiling Main ( test.hs, interpreted ) Ok, modules loaded: Main. *Main> :main True
めでたしめでたし。せっかく TypeApplications
を使うなら、 f
の定義ももう少し簡潔になる。
f :: forall a. (Show a, Read a) => String -> String f = show @a . read
AllowAmbiguousTypes
の妥当性型変数作って TypeApplications
使って適用したいだけなのに突然 AllowAmbiguousTypes
拡張が出てきてなんだよって思ったかもしれないが、
論文中ではこいつの必要性は書いてあって、そもそもは TypeApplications
を有効にすると自動的に有効になるようになってた。
このへんのメールのやり取り でない方がいいだろって話になって、 このコミットで消された。
Proxy
TypeApplications
を使えるコンパイラを持っていないあなたでも、型の役割をする式である Proxy
型を使うことができるのだ!
副作用で型の本文に a
が入るようになるので、 AllowAmbiguousTypes
拡張も不要になる。
{-# LANGUAGE ScopedTypeVariables #-} import Data.Proxy f :: forall proxy a. (Show a, Read a) => proxy a -> String -> String f _ = (show :: a -> String) . read main :: IO () main = putStrLn $ f (Proxy :: Proxy Bool) "True"
だが、勘がいいあなたなら気がついてしまったかもしれない。 Proxy
は可読性をあげてくれるだけで、なくても困らないことを。
{-# LANGUAGE ScopedTypeVariables #-} f :: forall proxy a. (Show a, Read a) => proxy a -> String -> String f _ = (show :: a -> String) . read main :: IO () main = putStrLn $ f [False] "True"
GHCiのデフォルト型の割り当ては強力 なので、なんと f
がそのままコンパイルできてしまうのだ!! ただし、勝手に ()
になってしまう。
*Main> f = show . read *Main> f "()" "()" *Main> f "True" "*** Exception: Prelude.read: no parse
vagrantで ubuntu/zesty64 を使ったら、 https://github.com/commercialhaskell/stack/issues/2536 的なメッセージが出てかなりの高確率で stack setup
に失敗した。
そもそも安定版使ってないほうが悪かったので、 ubuntu/xenial64 使うようにしたら収まった。とは言え、その直前に zesty64 も senial64 もどちらのboxもアップデートされた(20170119.1.0)っぽいので、何が悪かったかは切り分けてない。
最近ひどく疲れているので http://www.toshin.com/center/ から英語を解いた。リスニングが42点で筆記が169点。おもったよりひどくないと思ってしまったけど、本来満点取らないと駄目なやつだよね、これ。現役の頃を思い出して気分転換にはなったので良しとする。こうやって明確に解法も解答も決まっているのは頭の準備体操にはいいね。
packages: drawille: .. 省略 .. version: '0.1.2.0' .. 省略 .. description: cabal-version: '1.10' modules: - System.Drawille provided-exes: - image2term - senoid packages: base: components: - library - test-suite range: ==4.* hspec: components: - test-suite range: ! '>=1.11 && <2.4' containers: components: - library - test-suite range: ==0.5.* QuickCheck: components: - test-suite range: ! '>=2.6' tools: {} shakespeare: .. 省略 ..
SimpleTarget
は Stack.Build.Target#resolveRawTarget で決めてるDuplicateRecordFields
を実装した影響だと思うけど、 ghci で重複するレコード名を定義したときの振る舞いが 7.10 と 8.0 で違ってる。
まず 7.10 。「フィールド定義が消される」という振る舞いに見える。
$ stack --resolver ghc-7.10 ghci Configuring GHCi with the following packages: GHCi, version 7.10.3: http://www.haskell.org/ghc/ :? for help Prelude> data X = X { x :: Bool } Prelude> data Y = Y { x :: Int } Prelude> let anX = X { x = True } <interactive>:18:11: Constructor ‘X’ does not have field ‘x’ In the expression: X {x = True} In an equation for ‘anX’: anX = X {x = True} Prelude> let anX = X { x = 10 } <interactive>:19:11: Constructor ‘X’ does not have field ‘x’ In the expression: X {x = 10} In an equation for ‘anX’: anX = X {x = 10} Prelude> :t anX <interactive>:1:1: Not in scope: ‘anX’ Perhaps you meant one of these: ‘and’ (imported from Prelude), ‘any’ (imported from Prelude)
8.0 で同じことをやってみる。フィールドがないことを検知してないように思える。気持ち悪いのは、 True
を渡すと値を生成できてしまうこと。しかも True
はなかったことにされて x
フィールドの値を評価すると例外が投げられる。
$ stack ghci Configuring GHCi with the following packages: GHCi, version 8.0.1: http://www.haskell.org/ghc/ :? for help Loaded GHCi configuration from C:\tools\msys64\tmp\ghci1668\ghci-script Prelude> data X = X { x :: Bool } Prelude> data Y = Y { x :: Int } Prelude> let anX = X { x = True } <interactive>:67:11: warning: [-Wmissing-fields] • Fields of ‘X’ not initialised: x • In the expression: X {x = True} In an equation for ‘anX’: anX = X {x = True} Prelude> let anX = X { x = 10 } <interactive>:68:19: error: • No instance for (Num Bool) arising from the literal ‘10’ • In the ‘x’ field of a record In the expression: X {x = 10} In an equation for ‘anX’: anX = X {x = 10} Prelude> :t anX anX :: X Prelude> let (X x') = anX in x' *** Exception: <interactive>:3:11-24: Missing field in record construction x
これが起こるのは REPL 上だけで、ソースコード上でフィールド名が重複していれば当然コンパイルが通らないので、大きな問題ではないだろう。そもそも 7.10 系の振る舞いが理想的かってのもある。バグな気はするけど。