LoginSignup
2
1

More than 5 years have passed since last update.

アンボックス化タプルの挙動を確認(微妙)

Last updated at Posted at 2015-01-05

Haskellの実験メモです。

普通のタプルとアンボックス化タプルの違いを、簡単なパターンマッチで検出できるかどうか試しました。1要素のタプルはないので1要素のデータ型で代用しました。結論から言うとこの方法では違いを検出できません。代用がこれで良いのか微妙ですが。

ネタ元

datanewtypeの違いというのはよく話題になって、undefinedに対するパターンマッチで検出するのが定石です。

以下に正格性注釈も交えた比較が載っています。

これを元にundefinedでアンボックス化タプル特有の挙動が見られるかどうかを確認しました。

テストコード

ghciで確認すると再現が面倒なので、HUnitでテストしました。

uundefinedが返って来ることを示しています。

{-# LANGUAGE UnboxedTuples #-}

import Test.HUnit
import System.IO
import Control.Exception

undef :: Int -> ErrorCall -> IO Int
undef x _ = return x

t :: String -> Int -> Int -> Test
t s x t = s ~: (~? s) $ do
    v <- catch (evaluate t) $ undef u
    return $ x == v

u = 0

data Foo1 = Foo1 Int
data Foo2 = Foo2 !Int
newtype Foo3 = Foo3 Int
data Foo4 = Foo4 (# Int #)

tests = TestList
    [ t "a1" 1 $ case Foo1 undefined of Foo1 _ -> 1
    , t "a2" u $ case Foo2 undefined of Foo2 _ -> 1
    , t "a3" 1 $ case Foo3 undefined of Foo3 _ -> 1
    , t "a4" u $ case Foo4 undefined of Foo4 _ -> 1
    , t "a5" u $ case Foo4 undefined of Foo4 (# _ #) -> 1

    , t "b1" u $ case undefined of Foo1 _ -> 1
    , t "b2" u $ case undefined of Foo2 _ -> 1
    , t "b3" 1 $ case undefined of Foo3 _ -> 1
    , t "b4" u $ case undefined of Foo4 _ -> 1
    , t "b5" u $ case undefined of Foo4 (# _ #) -> 1
    , t "b6" u $ case undefined of      (# _ #) -> 1
    , t "b7" 1 $ case undefined of         _    -> 1

    , t "c1" 1 $ case    undefined    of    _    -> 1
    , t "c2" 1 $ case (  undefined  ) of (  _  ) -> 1
    , t "c3" 1 $ case (# undefined #) of (# _ #) -> 1
    , t "c4" 1 $ case (  undefined, undefined  ) of (  _, _  ) -> 1
    , t "c5" 1 $ case (# undefined, undefined #) of (# _, _ #) -> 1

    , t "d1" 1 $ case undefined of    _    -> 1
    , t "d2" 1 $ case undefined of (  _  ) -> 1
    , t "d3" u $ case undefined of (# _ #) -> 1
    , t "d4" u $ case undefined of (  _, _  ) -> 1
    , t "d5" u $ case undefined of (# _, _ #) -> 1
    ]

main = do
    runTestText (putTextToHandle stderr False) tests
実行結果
Cases: 22  Tried: 22  Errors: 0  Failures: 0
  • a2, a4, b2, b4: データ型で包んだ場合、正格性注釈を加えたものとアンボックス化タプルの挙動は同じです。
  • b5, b6: データ型で包んだものと単独のアンボックス化タプルでは、挙動に違いは見られません。
  • c1, c2, d1, d2: _(_)は同じものです。単独の値を1要素のタプルだと見なすのはおかしいので、以下では1要素のデータ型Foo1で代用します。
  • a1, c3, b1, d3: 1要素のデータ型と1要素のアンボックス化タプルの挙動に違いは見られません。
  • c4, c5, d4, d5: 2要素の通常のタプルとアンボックス化タプルの挙動に違いは見られません。

参考

例外をcatchするのにevaluateで正格評価しないとすり抜けることがあるのを知らずにハマりました。次の記事に明記されています。

次の記事では、datanewtypeの違いをタプルを交えて図解しています。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1