이 질문을 올린 지 1 년이 지났습니다. 그것을 게시 한 후, 나는 몇 달 동안 하스켈을 탐구했다. 나는 그것을 대단히 즐겼다. 그러나 나는 내가 모나드를 탐구 할 준비가 된 것처럼 그것을 옆으로 두었다.나는 일하러 돌아 왔고 프로젝트에 필요한 기술에 집중했다.
그래서, 여기에 코멘트입니다 -이 sylvan으로 the comment here의 모든 직접 인용입니다 :
이 꽤 멋지다. 그래도 조금 추상적입니다. 나는 어떤 모나드가 실제 예가 부족하기 때문에 이미 혼란스러워하는지 모르는 사람들을 상상할 수 있습니다.
그래서 내가 따르도록 노력하겠습니다.보기 흉하게 보일지라도 C#에서 예제를 할 것입니다. 최종적으로 상응하는 하스켈을 추가하고 멋진 하스켈 신택스 설탕을 보여 드리겠습니다. 모조품이 실제로 유용 해지기 시작하는 곳입니다.
좋아, 그래서 가장 쉬운 Monads 중 하나는 하스켈에서 "아마 모나드"라고합니다. C#에서는 Maybe 형식을 Nullable<T>
이라고합니다. 이것은 기본적으로 유효하고 값이 있거나 값이 "null"이고 값이없는 값의 개념을 캡슐화하는 아주 작은 클래스입니다.
이 유형의 값을 결합하기 위해 모나드 내부에 붙이는 데 유용한 것이 실패의 개념입니다. 나는. 우리는 여러 nullable 값을보고 그들 중 하나가 null이 되 자마자 null
을 반환 할 수 있기를 원합니다. 예를 들어, 사전이나 무언가에서 많은 키를 찾으면 결국 모든 결과를 처리하고 어떻게 든 결합하기를 원하지만 어떤 키가 사전에없는 경우 유용 할 수 있습니다. 당신은 모든 것을 위해 null
을 돌려주고 싶다. null
에 대한 각 조회를 수동으로 확인하고 리턴해야하기 때문에 바인드 연산자 내에서이 검사를 숨길 수 있으므로 (이 문제는 모나드 (monads)와 비슷합니다. 코드를 더 쉽게 만드는 바인드 연산자에서 장부 보관을 숨 깁니다. 우리가 세부 사항을 잊을 수 있기 때문에 사용하는 것).
여기에 모든 것을 유발하는 프로그램이 있습니다 (나중에 Bind
을 정의 하겠지만, 이는 왜 좋은지를 보여주기위한 것입니다).
class Program
{
static Nullable<int> f(){ return 4; }
static Nullable<int> g(){ return 7; }
static Nullable<int> h(){ return 9; }
static void Main(string[] args)
{
Nullable<int> z =
f().Bind(fval =>
g().Bind(gval =>
h().Bind(hval =>
new Nullable<int>(fval + gval + hval))));
Console.WriteLine(
"z = {0}", z.HasValue ? z.Value.ToString() : "null");
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
}
지금, 이미 (당신이 함께 널 (NULL)의 int를 추가 할 수 있습니다 중 하나가 null의 경우는 null를 얻을) C#으로 Nullable
이 작업을 수행하기위한 지원이 있음을 잠시 무시합니다. 그런 기능이 없다고 가정하고 특수 마법이없는 사용자 정의 클래스 일뿐입니다. 요점은 Bind
함수를 사용하여 변수를 Nullable
값의 내용에 바인딩 한 다음 이상한 일이없는 것처럼 가장하고 정상적인 int처럼 사용하고 그냥 함께 추가하는 것입니다. 결과는 nullable로 끝나며 nullable은 null이됩니다 (f
, g
또는 h
이 null을 반환하는 경우). f
, g
및 h
을 합산 한 결과가됩니다. (이것은 데이터베이스의 한 행을 LINQ의 변수에 바인드하는 방법과 비슷합니다. Bind
연산자가 변수에 유효한 행 값만 전달된다는 것을 알고 안전합니다).
f
, g
및 h
중 하나를 null로 반환하면 전체가 null을 반환합니다.
바인드 연산자가 우리를 위해이 검사를 수행해야하고 null 값을 만나면 null을 반환하고 그렇지 않으면 Nullable
구조 내부의 값을 람다로 전달합니다.
다음은 Bind
운영자 : 여기
public static Nullable<B> Bind<A,B>(this Nullable<A> a, Func<A,Nullable<B>> f)
where B : struct
where A : struct
{
return a.HasValue ? f(a.Value) : null;
}
유형은 비디오에서 같다. M a
(이 경우 C# 구문에서는 Nullable<A>
) 및 a
에서 M b
(, C# 구문의 함수)을 사용하고 M b
(Nullable<B>
)을 반환합니다.
코드는 단순히 nullable에 값이 들어 있는지 확인한 다음 그 값을 추출하여 함수에 전달합니다. 그렇지 않으면 null 만 반환합니다. 즉, Bind
연산자가 모든 null 검사 논리를 처리합니다. 만약 우리가 Bind
이라고 부르는 값이 null이 아니면 그 값은 람다 함수에 "전달"될 것이고, 그렇지 않으면 우리는 일찍 빠져 나가고 전체 표현식은 null이된다. 이렇게하면 모나드를 사용하여 작성한 코드가이 null 검사 동작에서 완전히 자유 롭습니다. 단지 Bind
을 사용하고 모나드 값 (예제 코드에서는 fval
, gval
및 hval
) 내의 값에 바인딩 된 변수를 얻고 우리는 Bind
이 그것들을 전달하기 전에 null을 체크하는 것을 처리 할 것이라는 지식에서 그들을 안전하게 사용할 수 있습니다.
모나드로 할 수있는 다른 예가 있습니다. 예를 들어 Bind
연산자가 문자의 입력 스트림을 처리하고 파서 연결자를 쓰는 데 사용할 수 있습니다. 각각의 파서 연결자는 역 추적, 파서 실패 등과 같은 것을 완전히 무시할 수 있습니다. 더 작은 파서를 함께 결합하면 Bind
의 영리한 구현이 뒤에있는 모든 논리를 정렬합니다. 어려운 비트. 그러면 나중에 누군가가 모나드에 로깅을 추가하지만 모나드를 사용하는 코드는 변경되지 않습니다. 왜냐하면 모든 마법은 Bind
연산자의 정의에서 발생하기 때문에 코드의 나머지 부분은 변경되지 않습니다.
마지막으로 하스켈에서 동일한 코드를 구현 한 것입니다 (--
은 주석 행을 시작 함). 당신이 볼 수 있듯이
-- Here's the data type, it's either nothing, or "Just" a value
-- this is in the standard library
data Maybe a = Nothing | Just a
-- The bind operator for Nothing
Nothing >>= f = Nothing
-- The bind operator for Just x
Just x >>= f = f x
-- the "unit", called "return"
return = Just
-- The sample code using the lambda syntax
-- that Brian showed
z = f >>= (\fval ->
g >>= (\gval ->
h >>= (\hval -> return (fval+gval+hval))))
-- The following is exactly the same as the three lines above
z2 = do
fval <- f
gval <- g
hval <- h
return (fval+gval+hval)
는 마지막에 좋은 do
표기는 바로 필수 코드처럼 보이게. 실제로 이것은 의도적으로 설계된 것입니다. 모나드는 명령형 프로그래밍 (mutable state, IO 등)에서 모든 유용한 것들을 캡슐화하는 데 사용할 수 있으며 명령형 문법과 같이 사용하면 좋지만 커튼 뒤에는 모나드뿐 아니라 바인드 연산자를 영리하게 구현할 수 있습니다! 멋진 점은 >>=
과 return
을 구현하여 자신의 모나드를 구현할 수 있다는 것입니다. 그렇게하면 해당 모나드도 do
표기법을 사용할 수있게됩니다. 즉, 기본적으로 두 가지 기능을 정의하여 자신의 작은 언어를 작성할 수 있습니다!
사실 C# 3.0 개발자입니다. .NET 3.5와 혼동하지 마십시오. 그 외에 좋은 질문입니다. – Razzie
LINQ 쿼리 식은 C# 3의 모나드 동작의 예입니다. –
여전히 중복 질문이라고 생각합니다. http://stackoverflow.com/questions/2366/can-anyone-explain-monads의 답변 중 하나는 http://channel9vip.orcsweb.com/shows/Going+Deep/Brian-Beckman-Dont-fear- the-Monads /, 주석 중 하나는 아주 멋진 C# 예제를 가지고 있습니다. :) – jalf