2020 年 12 月

2020-12-22 (Tue)

Web フォント

さくらのコントロールパネルをみていたら、Web フォントが使えるというので、 このサイトにも設定してみた。ここ を参照しつつ、

2020-12-21 (Mon)

メモ:

0.9.1 版むけ要対応項目 に、Haskell 2010 仕様カバーにむけて、 いま把握している要対処項目の一覧をまとめた。これは、もともと v0.9.2 で目指していた 内容かもしれない。

これらをすべて対処するのが仕様準拠にむけた「スタート」で、そこから、 仕様を準拠しているかどうかの検証がはじまる。

2020-12-20 (Sun)

issue#113 を少し調査

すでにレポジトリから testcases/ を削除してしまっているので、 過去のコミット からサルベージしつつ確認。

newtypepair.hs のまえに、newtypepair0.hs が通らないのだが、それは、derivied class の実装がまだだからというので、納得はできる。

…が、それを回避した newtypepair0b.hs がダメなのはなぜだろう?変だ。

$ cat newtypepair0b.hs
data Pair b a = Pair (a, b)

instance Functor (Pair c) where
  fmap f (Pair (x, y)) = Pair (f x, y)

instance (Show a, Show b) => Show (Pair b a) where
  show (Pair (x, y)) = "Pair (" ++ show x ++ "," ++ show y ++ ")"

main = print $ fmap (*100) (Pair (2, 3))
$ bunny testrun newtypepair0b.hs
/home/unno/bunny/0.9.0/bin/bunnyc -d ./jout/newtypepair0b --xno-implicit-prelude /home/unno/bunny/0.9.0/lib/Prelude.hs
/home/unno/bunny/0.9.0/bin/bunnyc -d ./jout/newtypepair0b --xlibrary-path /home/unno/bunny/0.9.0/lib newtypepair0b.hs
newtypepair0b/Main.java:71: error: cannot find symbol
      Expr t14 = (Expr) new AtomExpr(new Dict(new Dict_36_Prelude_46_Integer_64_Prelude_46_Functor()));
                                                  ^
  symbol:   class Dict_36_Prelude_46_Integer_64_Prelude_46_Functor
  location: class Main
1 error
testrun: failed to compile the java files.

Functor インスタンスを回避した、newtypepair0c.h は OK.

Functor がだめかというと、print $ fmap (*100) (Just 2) などは普通に実行できた。

newtypepair0b.hs の調査からだな。 その次に、derived class と newtype は並行して進められる。

data Pair b a = Pair a b のように、型変数の順序が逆になっていたり、 それを利用して、instance Functor (Pair c) のように最初の型変数のみ指定していたりするあたりに対応できていないんだろうなとは思う。

2020-12-15 (Tue)

Haskell Advent Calendar 15 日目

毎年恒例となった(している)、アドベントカレンダーむけの記事を書いた: Android むけ Haskell コンパイラをリリースしました!

かなり妥協して無理やり 0.9.0 版としたのだけど、 締め切りを設定したからこそ出来た、必要な妥協なんだろうなという感じ。

残項目の質と量を考えると、5 月に 1 版にたどり着くのも容易というわけではなさそう。 毎月マイナーバージョンをリリースしても、5、6 回なのかと思うと、たしかに短い。

こんな感じかも:

[Bunny] Project Euler の problem_2, 3 を Bunny で動かしてみる

ほんとは、目標と現状のギャップを捉えて、計画的にすすめるべきかなと思うのだけど、 ちょっと一息ついてからにしたい。

というので、気軽にできる感じのやつとして、Project Euler の回答例を前から試していくやつをすこし。

problem2.hs:

problem_2 = sum [ x | x <- takeWhile (<= 1000000) fibs, even x]
  where
    fibs = 1 : 1 : zipWith (+) fibs (tail fibs)

main = print problem_2

これを、runhaskell (GHC) と bunny で実行してみる:

$ runhaskell problem2.hs
1089154
$ bunny testrun problem2.hs
/home/unno/bunny/0.9.0/bin/bunnyc -d ./jout/problem2 --xno-implicit-prelude /home/unno/bunny/0.9.0/lib/Prelude.hs
/home/unno/bunny/0.9.0/bin/bunnyc -d ./jout/problem2 --xlibrary-path /home/unno/bunny/0.9.0/lib problem2.hs
1089154

うごいた。

二つ目の回答例では、Double への defaulting が効かないのがでた。つぎのように型注釈をつけてやれば、うごいた。

problem2b.hs:

problem_2 = sumEvenFibs $ numEvenFibsLessThan 1000000
  where
    sumEvenFibs n = (evenFib n + evenFib (n+1) - 2) `div` 4
    evenFib n = round $ ((2 + sqrt 5) ** (fromIntegral n) / sqrt 5 :: Double)
    numEvenFibsLessThan n =
      floor $ ((log (fromIntegral n - 0.5) + 0.5*log 5) / log (2 + sqrt 5) :: Double)

main = print problem_2

他の2つの回答例も大丈夫でした。

problem_2 = sumEvenFibsLessThan 1000000

sumEvenFibsLessThan n = (a + b - 1) `div` 2
  where
    n2 = n `div` 2
    (a, b) = foldr f (0,1)
             . takeWhile ((<= n2) . fst)
             . iterate times2E $ (1, 4)
    f x y | fst z <= n2 = z
          | otherwise   = y
      where z = x `addE` y
addE (a, b) (c, d) = (a*d + b*c - 4*ac, ac + b*d)
  where ac=a*c

times2E (a, b) = addE (a, b) (a, b)

main = print problem_2
-- Every third term is even, and every third term beautifully follows:                                         
-- fib n = 4*fib n-3 + fib n-6                                                                                 
evenFibs = 2 : 8 : zipWith (+) (map (4*) (tail evenFibs)) evenFibs

-- So, evenFibs are: e(n) = 4*e(n-1) + e(n-2)                                                                  
-- [there4]:4e(n)   = e(n+1) - e(n-1)                                                                          
--          4e(n-1) = e(n)   - e(n-2)                                                                          
--          4e(n-2) = e(n-1) - e(n-3)                                                                          
--          ...                                                                                                
--          4e(3)   = e(4)   - e(2)                                                                            
--          4e(2)   = e(3)   - e(1)                                                                            
--          4e(1)   = e(2)   - e(0)                                                                            
--         -------------------------------                                                                     
-- Total: 4([sum] e(k) - e(0)) = e(n+1) + e(n) - e(1) - e(0)                                                   
-- => [sum] e(k) = (e(n+1) + e(n) - e(1) + 3e(0))/4 = 1089154 for                                              
-- first 10 terms                                                                                              

sumEvenFibsBelow :: Int -> Int
sumEvenFibsBelow n = ((last $ take (x+1) evenFibs) +
                      (last $ take x evenFibs) -
                       8 + 6) `div` 4
  where x = length (takeWhile (<= n) evenFibs)

main = print $ sumEvenFibsBelow 1000000

problem_3 も Ok でした。