「学習まとめ-ハスカル-4」ハスカルデータタイプ


Haskellデータタイプ
Table of Constets
  • ハスキー基本知識
  • Haskyell重要データ構造-List
  • ハスキー一般データ構造
  • 4ハスキータイプ
  • 4.1データタイプの表示と表示
  • 4.1.1データタイプ
  • を確認する.
  • 4.1.2関数タイプの表現
  • 4.1.3基本データタイプ
  • 4.2タイプ(Type class)
  • 4.2.1どうしてタイプがありますか?
  • 4.2.2一般タイプ
  • 4.3新しいタイプを定義して使用する
  • 4.3.1新しいデータタイプを定義する
  • 4.3.2新しいデータタイプを使用する
  • 4.3.3類別名(Type Synnyms)
  • 4.3.4再帰的定義+タイプ変更元(Type variable)
  • 4.3.5新しいタイプをタイプクラスにする例
  • 1 ハスカルの基本知識
    2 Haskyell重要データ構造-List
    3 ハスカル常用データ構造
    4 ハスカルタイプ
    4.1 データタイプの表示と表示
    4.1.1 データの種類を表示
    ghci>:t 'a'
    'a' :: Char
    ghci>:t 3
    3 :: Num a => a
    ghci>:t 2.5
    2.5 :: Fractional a => a
    ghci>:t (1,2)
    (1,2) :: (Num t1, Num t) => (t, t1)
    ghci>:t [1,2]
    [1,2] :: Num t => [t]
    ghci>:t "string"
    "string" :: [Char]
    
    4.1.2 関数の種類の表現
    特別なところは関数の種類です.
    ghci>:t head
    head :: [a] -> a
    
    上記のhead関数は、タイプは[a]->aであり、パラメータはListタイプであるという意味であり、List要素はaタイプであり、戻り値はaタイプである.ここのaは タイプ変更元(Type variable)は、変数です.取得値は整数、文字、浮動小数点などの具体的なタイプです.また、複数のパラメータの関数、例えばmap
    ghci>:t map
    map :: (a -> b) -> [a] -> [b]
    
    これは、mapには2つのパラメータがあり、最初のパラメータは関数であり、タイプはa>bであり、この関数のタイプはaタイプのパラメータを受け入れて、bタイプの結果を返します.第二のパラメータはListであり、要素タイプはaである.戻り結果は、Listであり、要素タイプはbである.
    前に関数を定義した時は、C、C+++、Javaなどの言語定義関数とは異なる関数の種類を指定していませんでした.このようにすることができるのは、Haskellのタイプシステムは関数のタイプを推定することができるので、関数のタイプが与えられていなくても、間違ったパラメータを入力すると、Haskellはエラーメッセージを与えます.
    もちろん、関数の種類も与えられます.方法は以下の通りです.
    charReverse :: [Char] -> [Char]
    charReverse [] = []
    charReverse (x:xs) = charReverse xs ++ [x]
    
    ghci>:t charReverse 
    charReverse :: [Char] -> [Char]
    ghci>charReverse "asdf"
    "fdsa"
    
    4.1.3 基本データタイプ
  • Int:範囲がある整数を表す
  • Integer:範囲のない整数を表す
  • Float、Double、Bool、Char:あなたが知っている
  • Tuple:前に
  • を紹介しました.
    4.2 タイプタイプ(Type class)
    4.2.1 なぜタイプがありますか?
    このような関数を見ます.チェックしてください
    ghci>:t (==)
    (==) :: Eq a => a -> a -> Bool
    
    この関数のタイプはa->a->Boolで、つまり同じタイプのパラメータを2つ受信して、Boolタイプの値を返します.例えば、
    ghci>3 == 4
    False
    ghci>3.1 == 3.2
    False
    ghci>'a' == 'b'
    False
    
    この関数はパラメータの特定のタイプを与えていません.二つのパラメータのタイプが同じでなければならないということを示していますが、これだけ満足すれば=関数で等しいと判断できますか?もちろんです.さもなくば後で私達は新しいタイプを定義して、教えません==何が等しいことを叫ぶことができますか?したがって、==のパラメータタイプを制限しなければなりません.これが前のEq aの役割です.ここのEqはタイプAです.タイプaはEqの一例でなければいけないということです.Eqの例としては、いくつかの関数を実装する必要があります.これらの関数は、=がどのような条件を満たすかを教えてくれます.この2つの要素は同じです.したがって、すべての種類の要素が==のパラメータを行うことができるわけではなく、Eqのインスタンスのタイプでなければならない.
    4.2.2 共通のタイプ
  • Eq:1つのタイプがその例となり、このタイプの2つの要素が等しいかどうかを==で比較することができる.
  • ghci>:t (==)
    (==) :: Eq a => a -> a -> Bool
    ghci>3 == 4
    False
    
  • Ord:1つのタイプがその例となり、このタイプの2つの要素の大きさを比較するために用いられます.
  • ghci>:t (>)
    (>) :: Ord a => a -> a -> Bool
    ghci>3 > 4
    False
    ghci>3 == 4
    False
    ghci>3 < 4
    True
    ghci>3 /= 4
    True
    
    ghci>:t compare 
    compare :: Ord a => a -> a -> Ordering
    ghci>3 `compare` 4
    LT
    ghci>3 `compare` 3
    EQ
    ghci>4 `compare` 3
    GT
    
  • Show:一つのタイプがその例となり、ghciはどのようにそれを表示するかを知っています.
  • ghci>show 3
    "3"
    ghci>show 4
    "4"
    ghci>show ['a','b']
    "\"ab\""
    ghci>show "ab"
    "\"ab\""
    
  • Read:一つのタイプがその例となり、ghciは読み取ったものをこのタイプとすることができます.
  • ghci>:t read
    read :: Read a => String -> a
    ghci>read "5" :: Int
    5
    ghci>read "5" :: Float
    5.0
    
  • Enum:一つのタイプがその例となり、このタイプの要素は順番に列挙できます.
  • Bounded:1つのタイプがその例となり、このタイプの要素は上界と下界がある.
  • Num:1つのタイプがその例となり、このタイプの要素は数字と類似した挙動を持っている.例えばInt、Integer、Float、DoubleはNumの例です.
  • Floating:FloatとDoubleはその例である.
  • Integral:IntとIntegerはその例です.
  • 4.3 新しいタイプを定義して使用します.
    4.3.1 新しいデータタイプを定義します.
    まず標準倉庫でデータの種類はどう定義されていますか?
    data Bool = False | True
    data Int = -2147483648 | -2147483647 | ... | -1 | 0 | 1 | 2 | ... | 2147483647
    
    データの種類が使えます. ダタ キーワードで定義します.私たちは自分のデータタイプを定義します.形状というデータタイプを定義するなら、形は丸いかもしれないし、長方形もあります.このように定義できます.
    data Shape = Circle Float Float Float | Rectangle Float Float Float Float
    
    ここの Circule 和 Rectangle 私たちは値の構造を表すと言いますが、これはどういう意味ですか?それらのタイプを見てみます.
    ghci>:t Circle 
    Circle :: Float -> Float -> Float -> Shape
    ghci>:t Rectangle 
    Rectangle :: Float -> Float -> Float -> Float -> Shape
    
    このように見ると、関数と同じです.なぜこのように表示しますか?Shapeは一つのタイプで、一つのタイプは常に決定された値が必要です.Intタイプが1,2,3あるような値です.では、どのようにShapeの値を表しますか?Shapeの値は同じ形では表現できません.円は三つの値が必要です.矩形は四つの値が必要です.ですから、値の構造子という概念を導入して、異なる形の値を統一します.たとえば:
    ghci>:t (Circle 1 2 3)
    (Circle 1 2 3) :: Shape
    ghci>:t (Rectangle 1 2 3 4)
    (Rectangle 1 2 3 4) :: Shape
    
    (Circul 1 2 3)と(Rectangle 1 2 3 4)はいずれもShapeタイプの値です.
    4.3.2. 新しいデータタイプを使う
    新しいタイプを定義すると、この新しいタイプでいくつかの関数を書くことができます.
    area :: Shape -> Float
    area (Circle _ _ r) = pi * r * r
    area (Rectangle x1 y1 x2 y2) = (abs $ x2 - x1) * (abs $ y2 - y1)
    
    ghci>area (Rectangle 1 2 3 4)
    4.0
    ghci>area (Circle 1 2 3)
    28.274334
    
    もちろん、データの種類Pointをもう一つ定義して、PointでShapeを構成してもいいです.
    data Point = Point Float Float
    data Shape = Circle Point Float | Rectangle Point Point
    
    また、もし私たちがghciにCircure 1 2 3を直接入力したら、正常に表示できません.彼らをどう表示しますか?前に言ったタイプが役に立ちましたが、表示するにはショーの実例になる必要があります.どうやってショーの実例になりますか?deringを使うだけです.
    data Shape = Circle Float Float Float | Rectangle Float Float Float Float
               deriving (Show)
    
    ghci>Circle 1 2 3
    Circle 1.0 2.0 3.0
    
    どのようにショーの実例になるか、すなわち表示の方式を具体的に定義していませんが、ようやく正常に表示できるようになりました.ここではデフォルトの表示方式を使用しています.
    また、新しいタイプのデータを使用する場合は、a=Circure 1 2 3なら、どのようにaを通して中の値1 2 3を取得しますか?私たちは三つの関数を書くことによって得られます.
    mrx (Circle x _ _ ) = x
    mry (Circle _ y _ ) = y
    mr (Circle _ _ vr ) = vr
    
    ghci>let a = (Circle 1 2 3)
    ghci>mrx a
    1.0
    ghci>mry a
    2.0
    ghci>mr a
    3.0
    
    しかし、この方法は面倒くさいので、ハスカルはもう一つの方法を提供しました.
    data Shape = Circle {rx :: Float, ry :: Float, r :: Float} | Rectangle Float Float Float Float
               deriving (Show)
    
    ghci>let a = (Circle 1 2 3)
    ghci>rx a
    1.0
    ghci>ry a
    2.0
    ghci>r a
    3.0
    
    この方法は、データタイプを定義しながら、対応する値を取得する関数を定義します.
    4.3.3 カテゴリ名(Type Synnyms)
    以下のように「Char」という別名のStringを付けることで、タイプ名をより良い自己記述能力を持つことができる.
    type String = [Char]
    
    4.3.4 再帰的定義+タイプ変更(Type variable)
    次は木を定義します.木の定義は再帰的です.このように定義できます.
    data Tree a = EmptyTree | Node a (Tree a) (Tree a) deriving (Show)
    
    この木は空木か、結点値+左子樹+右子樹の形です.ここのaは結点値のタイプで、つまりtype variableで、Int、Floatなどのタイプを表すことができます.型変元の概念を導入しないと、どのタイプの木にも定義されるのではないですか?Nodeは値構造子で、結点値+左子樹+右子樹を結合して、Treeタイプの値を構成しています.
    4.3.5 新しいタイプをタイプにする例
    以前はタイプの概念を説明しましたが、例えば、Eqはタイプの種類で、新しいタイプは==関数を使いたいなら、Eqの一例でなければなりません.具体的なプロセスはここで紹介します.新しいタイプを定義したら
    data TrafficLight = Red | Yellow | Green
    
    この時、この新しいタイプは必然的に使えなくなります.==等しいかどうかを判断します.だから、私達は教えなければなりません.
    instance Eq TrafficLight where
      Red == Red = True
      Yellow == Yellow = True
      Green == Green = True
      _ == _ = False
    
    これは実例化の過程であり、それはイコールとは何かを教えてくれました.
    ghci>Red == Red
    True
    ghci>Red == Yellow
    False