Haskell Monad(모나드)란?
17721 단어 하스켈
요약
Functor: 함수는 권외에 있지만 인수의 값이 권내이면
<$> (fmap)
를 사용할 수 있다. Applicative : 함수도 인수의 값도 같은 권내이면
<*>
를 사용할 수 있다. functor 클래스형권내에 값(함수)을 소속시키기 위해서는 pure
를 사용할 수 있다. Monad:메소드 체인등에서 반환값은 권내이지만, 함수는 인수의 값이 권외에 있을 때에는
>>=
를 사용할 수 있다. return
는 값을 monad 클래스형권내에 소속시킬 때 사용한다. 상세
Monad를 이해하기 위해서는 Haskell에 대해 여기까지 배운 것을 총동원할 필요가 있다고 느꼈기 때문에 그들도 김에 정리.
간단한 유형
カインド(種):*
개념도
기능
형을 인수에 취해 어떠한 처리를 행한 결과를 형태로 해 돌려준다
유형 서명의 예
関数A : f Int -> String
関数B : f String -> Int
関数A : f Int -> Int
関数B : f String -> String
개념도
지역 <컨텍스트>
특정 유형이 동일한 동작과 특성을 가질 때 범위를 권이라고합니다.
형 인수를 가지는 데이터형은 형태 인수의 권리
지역 <컨텍스트>의 예
リスト: [Int]
データ型: type Data = Data Int | String
리스트의 값은 리스트권의 값이며, 데이터형의 값은 데이터형권의 값.개념도
컨테이너와 컨텍스트
데이터형을 가리키고 컨테이너라고 표현하는 경우가 있다.
컨테이너에 함수를 적용한 경우, 함수로 정의된 데이터형을 인수로 하여 연산을 행한다.
한편, 문맥에 함수를 적용한 경우, 컨테이너(데이터형)가 가지는 형 변수를 인수로 하여 연산이 행해진다.
예를 들어, 컨테이너로서의 리스트의 덧셈은 리스트의 연결을 의미하지만, 문맥으로서의 리스트의 덧셈은 리스트의 요소끼리의 합한 값을 돌려준다
-- コンテナとしてのリストの例
Prelude> "Hello" ++ ", " ++ "world."
"Hello, world."
-- コンテキストとしてのリストの例
Prelude> pure (+) <*> [1..5] <*> [6..10]
[7,8,9,10,11,8,9,10,11,12,9,10,11,12,13,10,11,12,13,14,11,12,13,14,15]
1. Functor (관수)
정의:
<$>(fmap):: Functor f => (a -> b) -> f a -> f b
지역 값 <형 변수>에 함수 적용Functor의 예
1. Functor형 클래스의 인스턴스 a가 인수
2. (a -> b): a에 함수(->)를 적용한 결과 b가 생성
3. Functor 형 클래스의 인스턴스에 처리 결과 b를 채우고 반환한다
예 1) 목록에서 값을 검색하여 처리하고 다른 목록으로 값을 채우고 결과를 반환합니다.
예 2) Maybe 형으로부터 값을 꺼내 처리를 실시해, Maybe 형에 채우고 결과를 돌려준다
개념도
2. Applicative(어플리케이티브)
정의:
<$>(fmap):: Functor f => (a -> b) -> f a -> f b
권의 값 <형 변수>를 꺼내 함수를 적용한 후 결과를 권에 담아※Functor로 정의된 메소드
정의:
<*>:: Applicative f => f (a -> b) -> f a -> f b
지역 값 <형 변수>에 함수 적용정의:
pure:: Applicative f => a -> f a
형을 Functor의 권에 담아Applicative 예제
1. Applicative 형 클래스의 인스턴스 a가 인수
2. f(a -> b): 인수와 반환값이 Applicative형의 함수를 적용한 결과 b를 생성
3. Applicative 형 클래스의 인스턴스에 처리 결과 b를 채우고 반환한다
Prelude> -- f (a -> b)型の関数を定義
Prelude> func1 = (^) <$> Just 4
Prelude> :t func1
func1 :: (Integral b, Num a) => Maybe (b -> a)
Prelude> -- f a を渡して処理を実行
Prelude> func1 <*> Just 2
Just 16
Prelude> -- Functorの圏に詰め込む
Prelude> functor = pure 6
Prelude> :t functor
functor :: (Applicative f, Num a) => f a
Prelude> -- pureと<*>を使った式
Prelude> pure (^2) <*> Just 4
Just 16
Prelude> -- 練習1
Prelude> (++) <$> Just "Say," <*> Just "Hello"
Just "Say,Hello"
Prelude> -- 練習2
Prelude> pure (+) <*> [1,2] <*> [3,4]
[4,5,5,6]
Prelude> -- 練習3
Prelude> pure (+) <*> (pure (+) <*> Just 4 <*> Just 3) <*> Just 3
Just 10
3. Monad(모나드)
정의:
<$>(fmap):: Functor f => (a -> b) -> f a -> f b
지역 값 <형 변수>에 함수 적용※Functor로 정의된 메소드
정의:
<*>:: Applicative f => f (a -> b) -> f a -> f b
권의 값 <형 변수>를 꺼내 권의 함수를 적용한 후 결과를 권에 담는다.※Applicative로 정의된 메소드
정의:
pure:: Applicative f => a -> f a
형을 Functor의 권에 담아※Applicative로 정의된 메소드
정의:
>>= :: Monad m => m a -> (a -> m b) -> m b
지역에서 값을 검색하고 함수를 적용한 결과를 지역에 넣습니다.정의:
return :: Monad m => a -> m a
값을 권에 담아정의:
>> :: Monad m => m a -> m b -> m b
연습
import qualified Data.Map as Map
type UserName = String
type GamerId = Int
type PlayerCredits = Int
-- このMapはGameIdに紐づくUserNameを持つ
userNameDB :: Map.Map GamerId UserName
userNameDB = Map.fromList [(1, "Asano Aiko")
, (2, "Katase Kaito")
, (3, "Sato Satoshi")
, (4, "Tanabe Kaede")
, (5, "Nanase Nanako")]
-- このMapはUserNameに紐づくクレジット情報を持つ
creditsDB :: Map.Map UserName PlayerCredits
creditsDB = Map.fromList [("Asano Aiko", 5000)
, ("Katase Kaito", 15000)
, ("Sato Satoshi", 3000)
, ("Tanabe Kaede", 152500)
, ("Nanase Nanako", 6500)]
-- GamerIdに紐づくデータを取得
lookupUserName :: GamerId -> Maybe UserName
lookupUserName gamerId = Map.lookup gamerId userNameDB
-- UserNameに紐づくデータを取得する
lookupCredits :: UserName -> Maybe PlayerCredits
lookupCredits userName = Map.lookup userName creditsDB
-- GamerIdからユーザーのクレジット情報を取得する関数
creditsFromGamerId :: GamerId -> Maybe PlayerCredits
creditsFromGamerId gamerId = lookupUserName gamerId >>= lookupCredits
-------------------------
-- Maybeを使わないでGamerIdからユーザーのクレジット情報を取得する関数
lookupCreditsWithoutMonad :: Maybe UserName -> Maybe PlayerCredits
lookupCreditsWithoutMonad Nothing = Nothing
lookupCreditsWithoutMonad (Just userName) = lookupCredits userName
creditsFromGamerIdWithoutMonad :: GamerId -> Maybe PlayerCredits
creditsFromGamerIdWithoutMonad gamerId = lookupCreditsWithoutMonad $ lookupUserName gamerId
*Main> :l monad-sample.hs
*Main> -- Monadを使わないで実装
*Main> creditsFromGamerIdWithoutMonad 1
Just 5000
*Main> creditsFromGamerIdWithoutMonad 100
Nothing
*Main> -- Monadを使って実装
*Main> creditsFromGamerId 5
Just 6500
*Main> creditsFromGamerId 50
Nothing
감상
Monad에서 정의되고 있는 함수가 어떤 의미를 갖고, 어떤 움직임을 하는지 개요 레벨이지만 파악할 수 있었다.
다만 잘 다루기 위해서는 익숙해져야 한다고 느꼈다.
Reference
이 문제에 관하여(Haskell Monad(모나드)란?), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/minarai/items/7b42bf39c2c631fc6b98텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)