Hutton本2に「newtypeで宣言するデータ型も再帰的にできる」って書いてあるんですが、これは誤りですよね? 再帰的にできるのは、data だけですよね?
newtype NewTypeRecursion a = N (Either (NewTypeRecursion a) a)
newtype Void = Void Void
みたいなのも使いましたよ.type
は型の計算が遅延しませんが, newtype
は遅延するのが強みだと思っていました(再帰型の場合は type
は無限再帰が起き停止しなくなりますが, newtype
は型上は data
と同じ扱いなので新しい型が作られるだけですね)Void
は「値を構成できない型」を作るためで,“矛盾“に相当します.定理証明をするためですね.newtype
で再帰型は割と使う人なのですが, Cofree
とかはnewtype Cofree f a = Cofree (a, f (Cofree f a))
data
を使うべきというのはそうですが)type
と newtype
, data
の大きな違いはtype
は再帰型が書けないが, newtype
/ data
は書ける (type
はインスタンスにできないが, newtype
/ data
はインスタンスにできるnewtype
はコンストラクタが実行時に無いように振舞うnewtype
で再帰ができると書いてしまうと、例を出すべきですが、例が初心者のレベルを超えていると思います。newtype
は再帰できるという説明は見つけられませんでした。newtype
が再帰できる」とは書かない方がいいと思います。H本をぱらっと読み返してみましたが、 newtype
は再帰できるという説明は見つけられませんでした。
すいません,確かに書いてないようですね.これは僕の勘違いでした.newtype Tree = Tree (Int, [Tree])
Fix
を出す必要はないんじゃないかと(これは, Hutton本1だと type declaration で書けない例として紹介されていますね)Tree
の例は素敵ですね。訳注にこれを書くのが補完し合っていていいかも。newtype
は、初版にはなく、第2版から入りました。print $ (unsafeCoerce True :: Int)
を実行してみたら 2305843009213693952
と表示されました。64bit に変換すると 0010000000000000000000000000000000000000000000000000000000000000
になり、GHCの内部表現と関係していそうなんですけど、どうしてこうなるんですか?ghci> import Unsafe.Coerce ghci> print $ (unsafeCoerce (-1::Int) :: Word) 18446744073709551615
print (unsafeCoerce True :: IntOrBool)
が SEGV になったのは, 5764607523051092410
をBool値のヒープを指し示すポインタだと思って飛ぼうとしたせいだと思いますね.Bool値のコンストラクタはフィールドを特に持たないので,フィールドじゃない領域をフィールドだと思って参照した結果,そういう結果が返ってくるんだと思います(主に True だと True_closure + 9 , False だと False_closure + 8 を I64 表現だと解釈した結果こういう表示になってるようです.毎回実行するごとに結果が変わっていたので,多分空いてるヒープ領域なんだと思います)ghci> main -4035224716524808016
$ runghc Unsafe.hs -4035224717148402896 $ runghc Unsafe.hs -4035224717726351680
+--------+--------+--------+ |info ptr|payload1|payload2|.. +--------+--------+--------+
Bool型のTrueコンストラクタの場合 info ptr +--------+ | Trueへ | (ここは無し) +--------+ Int型の数値の場合 info ptr payload1 +--------+--------+ | I#へ | Int値 | +--------+--------+