LoginSignup
5
1

More than 5 years have passed since last update.

Freer Effectsが、だいたいわかった: 10. 存在型による拡張可能なデータ構造(Open Union)

Last updated at Posted at 2017-10-11

Freer Effectsが、だいたいわかった: 10. 存在型による拡張可能なデータ構造(Open Union)

目次

(0). 導入

  1. Freeモナドの概要
    • Freeモナドとは
    • FreeモナドでReaderモナド、Writerモナドを構成する
  2. 存在型(ExistentialQuantification拡張)の解説
  3. 型シノニム族(TypeFamilies拡張)の解説
  4. データ族(TypeFamilies拡張)の解説
  5. 一般化代数データ型(GADTs拡張)の解説
  6. ランクN多相(RankNTypes拡張)の解説
  7. FreeモナドとCoyoneda
    • Coyonedaを使ってみる
    • FreeモナドとCoyonedaを組み合わせる
      • いろいろなモナドを構成する
  8. Freerモナド(Operationalモナド)でいろいろなモナドを構成する
    • FreeモナドとCoyonedaをまとめて、Freerモナドとする
    • Readerモナド
    • Writerモナド
    • 状態モナド
    • エラーモナド
  9. モナドを混ぜ合わせる(閉じた型で)
    • Freerモナドで、状態モナドとエラーモナドを混ぜ合わせる
      • 両方のモナドを一度に処理する
      • それぞれのモナドを、それぞれに処理する
  10. 存在型による拡張可能なデータ構造(Open Union)
  11. 追加の言語拡張
    1. ScopedTypeVariables拡張
    2. TypeOperators拡張
    3. KindSignatures拡張
    4. ...
  12. モナドを混ぜ合わせる(開いた型で)
    • FreeモナドとOpen Unionを組み合わせる
    • 状態モナドにエラーモナドを追加する
  13. Open Unionを型によって安全にする
  14. Freer Effectsで、IOモナドなどの、既存のモナドを使用する
  15. 関数を保管しておくデータ構造による効率化
  16. いろいろなEffect
    • 関数handleRelayなどを作成する
    • NonDetについて、など

はじめに

存在型を使用した開かれた直和型について説明する。 存在型(ExistentialQuantification拡張)の解説も参照のこと。

いろいろな型の値を含むリスト

たとえば、Haskellでは、つぎのようなリストを定義することはできない。

[123, True, (), 'c']

こういうことをしたければ、つぎのようなデータ型を作る必要がある。

data Value
        = Unit ()
        | Bool Bool
        | Integer Integer
        | Char Char

このように定義しておけば、つぎのようなリストを定義することができる。

[Integer 123, Bool True, Unit (), Char 'c']

リストに含む型がはじめからわかっていれば、これでいい。それがあらかじめわかっていないとき、開かれた直和型が必要になる。

openUnion.hs
{-# LANGUAGE ExistentialQuantification, GADTs #-}
{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}

import Unsafe.Coerce

data UnionValue = forall x . UnionValue x

hetero :: [UnionValue]
hetero = [
        UnionValue (123 :: Integer), UnionValue True,
        UnionValue (), UnionValue 'c' ]

fromHetero :: [UnionValue] -> (Integer, Bool, (), Char)
fromHetero [UnionValue n, UnionValue b, UnionValue u, UnionValue c] = (
    unsafeCoerce n, unsafeCoerce b, unsafeCoerce u, unsafeCoerce c )

対話環境で試してみよう。

> :load openUnion.hs
> fromHetero hetero
(123,True,(),'c')

このデータ型であれば、あとから「値構築子を追加するのとおなじこと」ができる。

openUnion.hs
doubleValue :: UnionValue
doubleValue = UnionValue (123 :: Double)

これは、つぎのようにデータ型Valueに値構築子を追加したようなものである。

data Value
        = Unit ()
        | Bool Bool
        | Integer Integer
        | Char Char
        | Double Double

追加できる文脈

ここで、モナドを混ぜ合わせる(閉じた型で)でみた、データ型SEについて考える。

data SE s e a where
        Get :: SE s e s
        Put :: s -> SE s e ()
        Exc :: e -> SE s e a

これに、Wrierモナドの機能を追加して、つぎのようなデータ型とした。

data SE s e w a where
        Get :: SE s e w s
        Put :: s -> SE s e w ()
        Exc :: e -> SE s e w a
        Writer :: w -> SE s e w ()

おなじことを開いた直和型を使って実装してみよう。ここで、「開かれてい」てほしいのは機能または文脈であり、型変数aであらわされる型の値である、かえされる値については、開かれている必要はないことに注意する。

openUnion.hs
data Union a = forall t . Union (t a)

まずは、状態モナドの機能と、エラーモナドの機能とを、この型でまとめてみよう。

openUnion.hs
data State s a where
        Get :: State s s
        Put :: s -> State s ()

data Exc e a where
        Exc :: e -> Exc e a
    deriving Show

effects :: [Union ()]
effects = [Union $ Put (123 :: Integer), Union $ Exc "hello"]

データ型Excでだけ、deriving Showとしているのは、「試してみる都合上」だ。さらにWriterモナドの機能を追加してみる。データ型Writerを定義して、サンプルのリストeffectsを編集する。

openUnion.hs
data Writer w a where
        Writer :: w -> Writer w ()

effects :: [Union ()]
effects = [
        Union $ Put (123 :: Integer),
        Union $ Exc "hello",
        Union $ Writer "world" ]

fromUnion :: Union a -> t a
fromUnion (Union tx) = unsafeCoerce tx

Union型の値から、なかみを取り出す関数fromUnionも定義した。型エラーなどなく読み込めることを確認する。

> :load openUnion.hs
> :type effects
effects :: [Union ()]
> fromUnion $ effects !! 1 :: Exc String ()
Exc "hello"

データ型State、Exc、Writerのみっつを、おなじデータ構造に格納することができ、かつ、型がわかっていれば、そこから取り出せるということがわかった。

まとめ

存在型を使って、開かれた直和型を作ることができる。まずは、ふつうの開かれた型を作り、それから、「文脈についてだけ」開かれた直和型を作ってみた。

5
1
1

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
5
1