講義ノート「最初のプログラミング言語としてのHaskell」 パート1

画像

こんにちはHabr! 本日、私はセルゲイ・ミハイロヴィチ・アブラモフによる「最初のプログラミング言語としてのハスケル」コースで私の古い概要を取り上げ、この素晴らしい言語をできるだけ理解しにくい人に説明しようとします。 この物語は、準備のできていない読者を対象としています。 あなたが最初にHaskellという言葉を聞いたとしても...



第二部



Haskellベースタイプ


Haskell言語の基本タイプは次のとおりです。

数字

論理量

キャラクター

リスト

順序付きセット(タプル)

機能



数字

全体:

整数(-∞、∞)

Int(-2 ^ 31、2 ^ 31-1)

プレリュード(標準ライブラリ)には、浮動小数点数への変換(fromIntおよびfromInteger)を含む、整数に役立つ多くの機能が含まれています。



浮動小数点数:

フロート(小数点以下7桁)

ダブル(小数点以下16桁)



論理量

ブール(True | False)

結合、分離、および否定の演算(&&、||、not)



キャラクター

シャア( 'a')

そして、CharはIntで機能し、IntはChar(ord、chr)で機能します



リスト

リストは異なる場合があります。

[Int]-整数のリスト[1,2,3,4]

[Char]-文字のリスト(文字列)

[[Int]]-配列

[フロート->フロート]は機能のリストです

など



例のいくつかの標準操作:

Main> head [1,2,3]

1

メイン>テール[1,2,3]

[2,3]

メイン>長さ[True、False]

2

Main> reverse [1,2,3]

[3,2,1]

メイン> 0:[1,2,3]

[0,1,2,3]

Main>-ghciコンパイラコンソールのプロンプト行

「:」-アイテムをリストに添付する操作。



順序付きセット

例:

(2.4、「cat」)(フロート、[Char])

( 'a'、True、1)(Char、Bool、Int)

([1,2]、sqrt)([Int]、Float-> Float)

(1、(2、3))(Int、(Int、Int))



しかし、Haskellとすべての関数型プログラミングの中心は、もちろん関数そのものです!



機能


関数は、現代の数学では、特定のセットAの各要素xにセットBの単一の要素y(またはなし)を割り当てる対応法則です。

Haskellは、その目的により、まず第一に数学者の言語であるため、ここでの構文はこの定義に最も厳密に一致します。

例:

square :: Integer -> Integer square x = x*x
      
      





おそらくご想像のとおり、これは数値の2乗関数です。 詳細に分析します。



最初の行は関数宣言です:

関数名::定義スペース->値スペース

正方形::整数->整数

Haskellでは、常に関数を宣言する必要はないということを言っておかなければなりません。 場合によっては、インタープリターはこの関数の定義と価値の領域をすでに理解しています。 ただし、広告を省略することは悪い考えです。



2行目は関数定義です。

Function_nameパラメーター= Calculation_rule

正方形x = x * x



パラメータのない関数は定数にすぎません:

 e :: Float e = exp 1.0
      
      







いくつかのパラメーターを持つ関数:

説明をしてくれたjanatemに感謝しますコメントを読んでください )。

 abcFormula :: Float -> Float -> Float -> [Float] abcFormula abc = [ (-b+sqrt(b*b-4.0*a*c))/(2.0*a), (-b-sqrt(b*b-4.0*a*c))/(2.0*a) ] --    ax^2+bx+c=0
      
      







代替のある関数定義


他の言語と同様に、Haskellには分岐構造があります。

例としてabs関数(モジュール)を使用して分析します。

もし...なら...その他...

 abs1 x = if x>=0 then x else -x
      
      







〜の場合〜

 abs2 x = case x>=0 of True -> x False -> -x
      
      







しかし、標準のifとcaseに加えて、Haskellには非常に美しく、最も使用されている分岐構造があります。 いわゆるセキュリティ表現 。 例:

 abs3 x | x>0 = x | x<0 = -x | otherwise = 0
      
      





直線は「at」と読む必要があります。

「入力パラメータxを使用したabs3関数は、x> 0の場合は値xを取り、x <0の場合は値-xを取り、その他の場合は値0を取ります」と読みます。

もちろん、2つのガード式の助けを借りてすべてを記録することもできましたが、3つ書き留めて、それらがいくつあってもよいことを明確にしました。

それ以外の場合、前戯では非常に簡単に定義されます:

 otherwise :: Bool otherwise = True
      
      





つまり、「そうでない」の代わりに「True」と書くことは可能ですが、これもまた悪い形です。



パターンマッチング


Haskellで最も一般的で効果的な手法の1つは、パターンマッチングです。 パラメータの代わりに、関数にパラメータがどのように見えるかの例を入れることができます。 サンプルに近づいた場合、関数が実行され、そうでない場合、次のサンプルに移動します。 たとえば、パターンを使用して再帰を通じて階乗を決定する:

 fact :: Integer -> Integer fact 0 = 1 fact n = n * fact (n-1)
      
      





同じことですが、ガード式の助けを借りて:

 fact :: Integer -> Integer fact n | n==0 = 1 | n>0 = n*fact (n-1)
      
      





リストには非常に一般的なパターンがあります:(x:xs)。 X-最初の要素を示し、XS-リストの残りの部分(最初の要素を除く)。 「:」-リストにアイテムを添付する操作。 前奏曲の例:

 head :: [a] -> a head (x:_) = x head [] = error "Prelude.head: empty list" tail :: [a] -> [a] tail (_:xs) = xs tail [] = error "Prelude.tail: empty list"
      
      





head関数は、入力として任意のリスト[a]を受け取り、このリストの最初の要素を返します。 tail関数は、入力として何か[a]のリストを取り、このリストから最初の要素を削除します。

「_」-この要素には関心がないことを意味します。



さて、今日は以上です。 興味があれば、近いうちに続編を書きます。



All Articles