그림의 편지함, 응용 프로그램 및 목록(ReasonML에서)

이것은 Functors, Applicatives, And Monads In Pictures Haskell에서 ReasonML까지의 번역입니다.
나는 이 일이 칭찬할 만하다고 생각하지 않는다. 만약 네가 이 글을 좋아한다면, 반드시 Aditya Bhargava () 원판의 작가에게 감사해야 한다.
다음은 간단한 값입니다.

우리는 이 값에 함수를 어떻게 응용하는지 안다.

간단해.어떤 값이든 상하문에 있을 수 있도록 확장해 봅시다.이제 컨텍스트를 값을 넣을 수 있는 상자로 상상할 수 있습니다.

현재, 이 값에 함수를 적용할 때, 상하문에 따라 다른 결과를 얻을 수 있다.이것은 편지, 응용 프로그램, 쪽지, 화살표 등이 모두 기초한 사상이다.
다음 두 가지 관련 컨텍스트를 정의하는 데이터 유형Maybe을 만듭니다.

module Maybe = {
  type t('a) =
    | Nothing
    | Just('a);
}
잠시 후, 어떤 대상이 Just(a)Nothing 일 때, 함수 응용 프로그램이 어떻게 다른지 볼 수 있습니다.우선 우리 편지에 대해 이야기합시다!

편지


값이 컨텍스트에 패키지되어 있을 때 일반 함수를 적용할 수 없습니다.

이것이 바로 fmap의 용무지이다.fmap 길거리에서 왔고 fmap 언어 환경에 대해 매우 유행한다.fmap 함수를 포장된 상하문에 어떻게 응용하는지 알고 있다.(+3)Just(2) 에 적용하려는 경우구현 가능fmap:
Maybe.fmap((+)(3), Just(2));
// Just(5)

빵!fmap 어떻게 완성했는지 보여주세요!

편지는 무엇입니까?

Functorfmap 함수를 정의하는 일종의 함수이다.
Haskell에서는 atype class로 정의됩니다.
ReasonML에서 우리는 아직 유형 클래스가 없지만 they are being worked on in OCaml, 따라서 ReasonML.
정의는 다음과 같습니다.
Functor는 정의fmap가 그 모든 데이터 유형에 어떻게 적용되는지를 나타낸다.다음은 fmap 작동 방식입니다.

그래서 우리는 이렇게 할 수 있다.
Maybe.fmap((+)(3), Just(2));
// Just(5)
여기에는 fmapJust 에 적용되는 방법이 지정됩니다.Nothing 모듈에 추가 fmap:
let fmap = (f, m) => {
  switch (m) {
  | Nothing => Nothing
  | Just(a) => Just(f(a))
  };
};
다음은 우리가 작문Maybe을 할 때 배후에서 발생한 일이다.

그럼 네Maybe.fmap((+)(3), Just(2));, fmap로 신청해 주시겠어요?

Maybe.fmap((+)(3), Nothing)
// Nothing
'매트릭스'의 머피스처럼 (+3) 무엇을 해야 할지 알고 있다.Nothing부터 시작해서 fmap로 끝내세요!Nothing선이다.이제 Nothing 데이터 형식이 존재하는 원인을 이해할 수 있다.예를 들어, 데이터베이스 레코드를 없음 fmap 의 언어로 처리하는 방법에 대해 설명합니다.
post = Post.find_by_id(1)
if post
  return post.title
else
  return nil
end
이 함수로 ReasonML에 간단한 Maybe 모듈을 만듭니다.
module Post = {
  type t = {
    id: int,
    title: "string,"
  };
  let make = (id, title) => {id, title};
  let fmap = (f, post) => f(post);
  let getPostTitle = post => post.title;
  let findPost = id => make(id, "Post #" ++ string_of_int(id));
};
이제 우리는 다음과 같이 쓸 수 있다.
Post.(fmap(getPostTitle, findPost(1)));
Maybe 게시물로 돌아가면 Post 제목을 사용합니다.만약 그것이 되돌아온다면 findPost, 우리는 되돌아갈 것이다 getPostTitle!깔끔하죠?
Haskell에서 NothingNothing 의 일반적인 접두사 버전입니다.
ReasonML에서 등가 별칭을 만들 수 있습니다.Dell<$> 모듈에 추가:
let (<$>) = fmap;
이제 우리는 다음과 같이 쓸 수 있다.
Post.(getPostTitle <$> findPost(1));
이것은 또 다른 예이다. 함수를 하나의 목록에 적용할 때 무슨 일이 일어날까?

목록도functor로 조작할 수 있습니다!
ReasonML에서는 목록 매핑 함수를 사용할 수 있습니다.
List.map
그래, 그래, 마지막 예: 한 함수를 다른 함수에 적용할 때 무슨 일이 일어날까?
이 경우 fmap 모듈을 정의할 수 있습니다 Post.
module Function = {
  let fmap = (f, g, x) => f(g(x));
};
이제 우리는 다음과 같이 쓸 수 있다.
Function.fmap((+)(3), (+)(1));
이것은 함수입니다.

다음은 다른 함수에 적용되는 함수입니다.

결과는 단지 다른 함수일 뿐이다!
let foo = Function.fmap((+)(3), (+)(2));
foo(10);
// 15
그래서 함수도 편지일 수 있어요!
함수에서 Function 을 사용할 때, 당신은 함수 합성을 하고 있을 뿐입니다!

응용 프로그램


응용 프로그램은 그것을 다음 단계로 끌어올린다.응용 프로그램을 사용하면 우리의 값은 편지처럼 상하문에 포장됩니다.

하지만 우리의 함수도 하나의 상하문에 포장되어 있다!

그래이 점을 깊이 파고들자.응용 프로그램은 농담을 할 줄 모른다.컨텍스트에 포장된 함수를 컨텍스트에 포장된 값에 적용하는 방법을 알고 있습니다.
응용 프로그램은 fmap 함수를 정의했습니다. Haskell에서도 fmap 함수입니다. ReasonML에서 별명을 만들 수 있습니다.
apply 모듈에 응용 프로그램 함수를 추가합니다.
let apply = (mf, mv) => {
  switch (mv) {
  | Nothing => Nothing
  | Just(v) =>
    switch (mf) {
    | Nothing => Nothing
    | Just(f) => Just(f(v))
    }
  };
};

let (<*>) = apply;
다음은 사용 예제입니다.
Maybe.(Just((+)(3)) <*> Just(2));
// Just(5)
우리는 또한 목록에 응용 프로그램 함수를 정의할 것이다.내장 <*> 모듈과 이름 충돌을 방지하기 위해 Maybe 모듈을 만듭니다.
module MyList = {
  type apply('a, 'b) = (list('a => 'b), list('a)) => list('b);

  let apply: apply('a, 'b) =
    (fs, xs) => List.flatten(List.map(f => List.map(f, xs), fs));

  let (<*>) = apply;
};
사용MyList을 하면 재미있는 상황이 생길 수 있다.예:
let funList = [(*)(2), (+)(3)];
let valList = [1, 2, 3];
MyList.(funList <*> valList);
// [2, 4, 6, 4, 5, 6]

이것은 네가 응용 프로그램으로 할 수 있지만, 편지로는 할 수 없다.어떻게 두 개의 매개 변수를 두 개의 포장 값으로 가져오는 함수를 응용합니까?
Maybe.((+) <$> Just(5));
// Just((+)(5))

Maybe.(Just((+)(5)) <$> Just(4));
// ERROR ??? WHAT DOES THIS EVEN MEAN WHY IS THE FUNCTION WRAPPED IN A JUST
어플리케이션:
Maybe.((+) <$> Just(5));
// Just((+)(5))

Maybe.(Just((+)(5)) <*> Just(3));
// Just(8)
List<*>을 한쪽으로 밀어낸다."큰 남자아이는 임의의 수량 매개 변수가 있는 함수를 사용할 수 있다."라고 그가 말했다."ApplicativeFunctor를 사용하면 임의의 수량의 포장되지 않은 값을 필요로 하는 함수를 받아들일 수 있습니다. 그리고 모든 포장 값을 전달하고 포장 값을 얻을 수 있습니다! 하하하!"
Maybe.((*) <$> Just(5) <*> Just(3));

명세서


명세서 이해 방법:
  • 컴퓨터 과학 박사 학위를 받았다.
  • 버려라. 너는 이 부분에서 그것을 필요로 하지 않기 때문이다!
  • 명세서에 새로운 전환점이 하나 추가되었다.
    편지는 함수를 포장 값에 적용합니다.

    응용 프로그램은 패키지 값에 패키지 함수를 적용합니다.

    monad는 함수를 적용합니다. 이 함수는 포장 값을 포장 값으로 되돌려줍니다.
    단자에는 함수<$>나 연산자 별명<*>이 있어 이를 실현한다.
    우리 예를 하나 봅시다.
    우선, 우리는 bind를 우리의 좋은 olbind 모듈에 추가해야 한다.
    let bind = (mv, f) => {
      switch (mv) {
      | Nothing => Nothing
      | Just(v) => f(v)
      };
    };
    
    let (>>=) = bind;
    

    가설 >>= 은 짝수에만 적용되는 함수입니다.
    ReasonML에서 Maybehalf 함수를 정의해야 합니다.
    /*
     Mutually recursive function
     https://ocaml.org/learn/tutorials/labels.html
     */
    let rec even = x =>
      if (x <= 0) {
        true;
      } else {
        odd(x - 1);
      }
    and odd = x =>
      if (x <= 0) {
        false;
      } else {
        even(x - 1);
      };
    
    let half = x =>
      if (even(x)) {
        Maybe.Just(x / 2);
      } else {
        Nothing;
      };
    

    만약 우리가 그것에게 포장의 값을 준다면?

    포장된 값을 함수에 밀어넣으려면 half 을 사용해야 합니다.이것은 even 사진입니다.

    다음은 작업 원리입니다.
    Maybe.(Just(3) >>= half);
    // Nothing
    
    Maybe.(Just(4) >>= half);
    // Just(2)
    
    Maybe.(Nothing >>= half);
    // Nothing
    
    안에서 무슨 일이 일어났습니까?odd 정의>>=(또는 >>= 함수:
    Monad 함수를 추가함으로써 bind 을 단자로 만듭니다.
    let bind = (mv, f) => {
      switch (mv) {
      | Nothing => Nothing
      | Just(v) => f(v)
      };
    };
    
    let (>>=) = bind;
    
    여기는 하나입니다>>=!

    만약 당신이 하나 Maybe 를 낸다면 더욱 간단합니다.

    이러한 호출을 링크할 수도 있습니다.
    Maybe.(Just(20) >>= half >>= half >>= half);
    


    멋있는 거!현재 우리는 bindJust(3), 및 Nothing 로 실현할 것이다.
    이제 다른 예로 넘어가서 Maybe 목록을 만듭니다.
    Functor 목록은 Haskell에 존재하지만, ReasonML에서 우리의 목록을 설명할 것입니다.
    구체적으로 말하면 세 가지 기능이 있다.Applicative 매개변수를 허용하지 않고 사용자 입력을 가져옵니다.
    Monad 문자열 (파일 이름) 을 가져와 파일의 내용을 되돌려줍니다.
    IO 문자열 가져오기 및 인쇄:

    우리의 IO 모듈은 이렇게 보일 수 있습니다. (helper 함수의 실현 세부 사항을 생략한 것):
    module IO = {
      type t = Js.Promise.t(string);
    
      type bind('a, 'b) = (t, string => t) => t;
      let bind: bind('a, 'b) = (pa, f) => pa |> Js.Promise.then_(a => f(a));
    
      let (>>=) = bind;
    
      type getLine = unit => t;
      let getLine = ...
    
      type readFile = string => t;
      let readFile = ...
    
      type putStrLn = string => t;
      let putStrLn = ...
    };
    
    관심 있으시면 full source code is available 을 클릭하십시오.
    이 세 함수는 모두 일반적인 값(또는 값이 없음)을 취하고 포장된 값getLine을 되돌려줍니다.우리는 readFile를 사용하여 이 모든 것을 연결할 수 있다!

    IO.(getLine() >>= readFile >>= putStrLn);
    
    오, 네!모나드 쇼 앞자리!

    결론

  • 편지는 putStrLn 함수를 실현하는 데이터 형식이다.
  • 응용 프로그램은 IO 함수를 실현하는 데이터 형식이다.
  • 단자는 Promise 함수를 실현하는 데이터 형식이다.
  • 우리 예시의 >>= 모듈은 이 세 가지를 실현했기 때문에 이것은 편지, 응용 프로그램과 명세서이다.
    이 세 사람 사이에는 어떤 차이가 있습니까?

    편지: 사용fmap 또는 apply 함수를 포장값에 적용합니다.
    응용 프로그램: bind 또는 Maybe 포장 함수를 사용하여 포장 값에 적용합니다.
    Monads: fmap 또는 <$> 를 사용하여 패키지 값을 반환하는 함수를 패키지 값에 적용합니다.
    그래서 친애하는 친구(나는 우리가 이 점에서 친구라고 생각한다), 나는 우리가 모두 리스트가 간단하고 총명한 생각이라는 것에 동의한다고 생각한다(tm).이 안내서에 군침을 삼켰으니 왜 메르 지부슨 하나를 끌고 병 전체를 잡지 않겠는가.이 것 좀 봐요section on Monads.나는 밀라노가 이 방면을 깊이 연구하는 데 매우 잘했기 때문에 많은 일을 감추었다.
    만약 당신이 내가 바꿀 수 있는 것이 있다고 생각한다면, 이 번역을 ReasonML로 개선하기 위해서 나에게 알려 주십시오.
    다시 한 번 감사 Aditya Bhargava 작성 original version of this post❤️

    좋은 웹페이지 즐겨찾기