Haskell:HaskellBasics
하스켈 기초 (Haskell Basics)
환경 갖추기 (Getting set up)
- Glasgow Haskell Compiler 즉 GHC 다운로드.
변수와 함수 (Variables and functions)
- https://wikidocs.net/1570
- 주석:
--
,{- ... -}
- 변수:
r = 10
- 함수:
area r = pi * r^2
-
where
절:
진위값 (Truth values)
- https://wikidocs.net/1605
- 중위 연산자 (e.g.
==
) 다음의 코드는 완벽히 동일하다.
- 가드 (Guard)
- 절대값 함수는 다음과 같다:
\(|x|=\begin{cases}x,&x\ge0\\-x,&x\lt0\end{cases}\) - 하스켈 코드는 다음과 같다:
- 절대값 함수는 다음과 같다:
abs x
| x < 0 = 0 - x
| otherwise = x
</syntaxhighlight>
-
- 위의 코드가 대응하는 수학적 정의만큼이나 가독성 있다는 것에 주목하자. 정의를 하나씩 해부해보겠다.
- 일반적인 함수 정의로 시작해, 함수 이름 abs를 쓰고, 이 함수가 단일 매개변수 x를 취한다고 알린다.
-
=
와 정의의 우변을 적는 대신 줄 바꿈을 하고, 두 대체문을 별개의 줄에 놓았다. 이 대체문들은 가드 (Guard)라고 하는 것들이다. 공백은 단순히 미(美) 적인 이유로 넣은 것이 아니다. 공백은 코드가 올바르게 파싱되게 하는 필수 요소다. - 각각의 가드는 파이프 문자
|
로 시작한다. 파이프 뒤에는 불리언 값으로 평가되는 표현식(불리언 조건식 또는 술어식(Predicate) 이라고도 부름)을 놓고, 그 다음 정의의 나머지 부분이 온다. 바로 술어식이 True로 평가될 경우 사용될, 등호와 우변이다. -
otherwise
분기는 선행하는 술어식들 중 True로 평가되는 게 없을 때 쓰인다. 위의 경우, x가 0보다 작지 않으면 0과 같거나 0보다 커야만 한다. 따라서 마지막 술어식을 x >= 0으로 쓸 수도 있었지만,otherwise
도 잘 작동한다.
- 위의 코드가 대응하는 수학적 정의만큼이나 가독성 있다는 것에 주목하자. 정의를 하나씩 해부해보겠다.
where
와 가드-
where
절은 특히 가드와 함께 쓸 때 편리하다. 2차 방정식 \(ax2+bx+c=0\) 의 (실수인) 해의 개수를 구하는 함수는 다음과 같다:
numOfSolutions a b c
| disc > 0 = 2
| disc == 0 = 1
| otherwise = 0
where
disc = b^2 - 4*a*c
</syntaxhighlight>
타입의 기초 (Type basics)
- 4 타입의 기초 - WikibooksHaskell
- https://en.wikibooks.org/wiki/Haskell/Type_basics
- GHCi에서 타입 확인하는 명령은
:type
(또는:t
) 이다:
Prelude> :type True True :: Bool
</syntaxhighlight>
- 문자는
Char
이고, 문자열은[Char]
이다. 참고로String
과[Char]
은 동일하다.
Prelude> :t 'H' 'H' :: Char Prelude> :t "Hello World" "Hello World" :: [Char]
- 함수 시그니처:
- 예제로,
xor
의 타입을 확인하면xor :: Bool -> Bool -> Bool
로 출력된다. -
::
의 좌측은 함수 이름. -
::
의 우측은 함수의 인자 목록으로,->
기호로 구분한다. - 단,
->
기호의 마지막에 있는 타입은 반환값 이다.
- 예제로,
let .. in
의 예제: capitalize :: String -> String capitalize x =
let capWord [] = []
capWord (x:xs) = toUpper x : xs
in unwords (map capWord (words x))
</syntaxhighlight>
리스트와 튜플 (Lists and tuples)
- 5 리스트와 튜플 - WikibooksHaskell
- Haskell/Lists and tuples - Wikibooks, open books for an open world
- 리스트:
Prelude> let numbers = [1,2,3,4] Prelude> let truths = [True, False, False] Prelude> let strings = ["here", "are", "some", "strings"]
</syntaxhighlight>
- 각괄호는 리스트의 범위를 제한하고, 개개의 원소들은 쉼표로 구분된다.
- 딱 하나 중요한 제한사항은 리스트 내의 모든 원소가 타입이 같아야 한다는 것이다.
- 타입이 혼재된 원소들의 리스트를 정의하려고 하면 전형적인 타입 오류가 발생한다.
- 리스트 컨싱 (Consing) [^0]
-
[1,2,3,4,5]
와1:2:3:4:5:[]
는 완전히 동치다.- 하지만 리스트 생성에는 잠재적인 함정이 있다.
True:False:[]
와 같은 것은 더할 나위 없이 훌륭한 하스켈 코드지만True:False
는 아니다.
- 하지만 리스트 생성에는 잠재적인 함정이 있다.
- 문자열도 리스트일 뿐이다:
-
Prelude>"hey" == ['h','e','y'] True Prelude>"hey" == 'h':'e':'y':[] True
</syntaxhighlight>
- 튜플:
(True, 1) ("Hello world", False) (4, 5, "Six", True, 'b')
</syntaxhighlight>
-
- 튜플 변경불가능 (Immutable) 이다. 즉, 튜플에 컨싱(cons)할 수 없다. 따라서 몇 개의 값이 저장될지 미리 아는 경우에 튜플을 사용하는 것이 타당하다.
- 튜플의 원소들은 같은 타입일 필요가 없다.
References
타입의 기초2 (Type basics II)
If/패턴/let
- 7 다음 과정 - WikibooksHaskell
-
if
/then
/else
:
mySignum x =
if x < 0
then -1
else if x > 0
then 1
else 0
</syntaxhighlight>
-
- 가드 문법으로 쉽게 재작성할 수 있다:
mySignum x
| x < 0 = -1
| x > 0 = 1
| otherwise = 0
</syntaxhighlight>
- 패턴 매칭의 도입:
pts 1 = 10 pts 2 = 6 pts x
| x <= 6 = 7 - x
| otherwise = 0
</syntaxhighlight>
-
- 또 다른 예시:
(||) :: Bool -> Bool -> Bool False || False = False _ || _ = True
</syntaxhighlight>
- 튜플 패턴과 리스트 패턴:
-- 예: head, tail, 그리고 패턴 head :: [a] -> a head (x:_) = x head [] = error "Prelude.head: empty list"
tail :: [a] -> [a] tail (_:xs) = xs tail [] = error "Prelude.tail: empty list"
</syntaxhighlight>
-
let
바인딩-
let
키워드를 선언 앞에 놓고,in
을 이용해 함수의 "주" 몸체로 돌아온다는 신호를 보낸다. 하나의let...in
블록 내에 여러 선언을 놓을 수 있다. 이것들이 같은 양만큼 들여쓰기 되었는지만 확실히 할 것. 그렇지 않으면 문법 오류가 발생한다:
-
roots a b c =
let sdisc = sqrt (b*b - 4*a*c)
twice_a = 2*a
in ((-b + sdisc) / twice_a,
(-b - sdisc) / twice_a)
</syntaxhighlight>
어휘 쌓기 (Building vocabulary)
함수 합성 연산자인 (.)
를 사용하면 된다.