Scala Functor와 Monad 차이점
누군가 Scala 맥락에서 Functor와 Monad의 차이점을 설명해 주시겠습니까?
스칼라 자체는 Functor
과 Monad
용어를 그다지 강조하지 않습니다 . 사용하는 map
것은 펑터 쪽이고, 사용하는 flatMap
것은 모나드 쪽입니다.
저에게 scalaz 를 둘러보고 노는 것은 지금까지 스칼라 컨텍스트에서 이러한 기능적 개념을 이해하는 가장 좋은 방법 이었습니다 (하스켈 컨텍스트에 비해). 2 년 전 스칼라를 시작했을 때 스칼라 즈 코드는 나에게 횡설수설이었고 몇 달 전에 다시 살펴보기 시작했고 이것이 특정 스타일의 함수형 프로그래밍을 정말 깔끔하게 구현 한 것임을 깨달았습니다.
예를 들어 Monad
구현은 모나드가 트레이 트 (트레이 트 뿐만 아니라)를 확장하기 때문에 포인트 펑터 임을 보여줍니다 . 코드를 보도록 초대합니다. 소스 자체에 링크가 있고 링크를 따라가는 것은 정말 쉽습니다.Pointed
Applicative
따라서 펑터가 더 일반적입니다. 모나드는 추가 기능을 제공합니다. 펑터가 있거나 모나드가있을 때 무엇을 할 수 있는지 알아 보려면MA
같은 암시 적 펑터 (특히 응용 펑터)가 필요한 유틸리티 메서드 sequence
와 replicateM
.
촬영 scalaz를 기준점으로서, 타입이 F[_]
함수는 그것으로 상승 될 수있는 경우 (즉, 어떤 하나의 입력에 의해 파라미터 화 된 타입 F)는 펑이다. 이것은 무엇을 의미 하는가:
class Function1W[A, B](self: A => B) {
def lift[F[_]: Functor]: F[A] => F[B]
}
즉, 함수 A => B
, 펑터가 F[_]
있으면 이제 함수가 F[A] => F[B]
있습니다. 이것은 스칼라의 map
방법 을 보는 것의 역방향 일뿐 CanBuildFrom
입니다. 기본적으로는 다음과 같습니다.
F[A] => (A => B) => F[B]
String에서 Int 로의 함수 인 List of Strings가 있다면 분명히 List of Int를 생성 할 수 있습니다. 이것은 Option, Stream 등에 적용됩니다. 모두 펑터입니다.
이것에 대해 흥미로운 점은 Functor가 A
s의 "컨테이너"라는 (잘못된) 결론으로 즉시 뛰어들 수 있다는 것 입니다. 이것은 불필요한 제한입니다. 예를 들어, 함수에 대해 생각해보십시오 X => A
. 기능 X => A
과 기능이 있으면 A => B
명확하게 구성별로 기능이 X => B
있습니다. 하지만 이제 다음과 같이보십시오.
type F[Y] = X => Y //F is fixed in X
(X => A) andThen (A => B) is X => B
F[A] A => B F[B]
따라서 일부 고정 X에 대한 유형 X => A도 펑터입니다. 에서 scalaz 형질이 같은 다음과 같이 펑 설계되어 있습니다 :
trait Functor[F[_]] { def fmap[A, B](fa: F[A], f: A => B): F[B] }
따라서 Function1.lift
위 의 방법이 구현됩니다.
def lift[F[_]: Functor]: F[A] => F[B]
= (f: F[A]) => implicitly[Functor[F]].fmap(f, self)
몇 가지 functor 인스턴스 :
implicit val OptionFunctor = new Functor[Option] {
def fmap[A, B](fa: Option[A], f: A => B) = fa map f
}
implicit def Functor1Functor[X] = new Functor[({type l[a]=X => a})#l] {
def fmap[A, B](fa: X => B, f: A => B) = f compose fa
}
에서 scalaz , 모나드는 다음과 같이 설계되어 있습니다 :
trait Monad[M[_]] {
def pure[A](a: A): M[A] //given a value, you can lift it into the monad
def bind[A, B](ma: M[A], f: A => B): M[B]
}
이것의 유용성이 무엇인지는 특별히 명확하지 않습니다. 대답은 "매우"라는 것이 밝혀졌습니다. 나는 Daniel Spiewak의 Monads가 왜 이것이 그럴 수 있는지를 설명 할 때 Metaphors가 아니라는 것을 발견했고 , 또한 독자 모나드를 통한 구성 에 대한 Tony Morris의 내용 , 모나드 내부에서 프로그램 을 작성 함으로써 의미 할 수있는 좋은 실용적인 예를 발견했습니다 .
얼마 전에 http://gabrielsw.blogspot.com/2011/08/functors-applicative-functors-and.html (저는 전문가가 아닙니다)
가장 먼저 이해해야 할 것은 'T [X]'유형입니다. 일종의 "컨텍스트"입니다 (유형을 인코딩하는 데 유용하며이를 "구성"하는 데 유용합니다.) 그러나 다른 답변을 참조하십시오. :)
좋아, 이제 컨텍스트 안에 타입이 있고, M [A] (A "inside"M)라고 말하면 일반 함수가 있습니다. f : A => B ... 계속해서 적용 할 수는 없습니다. 함수는 A를 예상하고 M [A]를 갖기 때문입니다. M의 내용을 "풀고"함수를 적용한 다음 다시 "포장"하는 방법이 필요합니다. M의 내부에 대한 "친밀한"지식이 있다면 할 수 있습니다. 특성으로 일반화하면 다음과 같이 끝납니다.
trait Functor[T[_]]{
def fmap[A,B](f:A=>B)(ta:T[A]):T[B]
}
이것이 바로 펑터입니다. 함수 f를 적용하여 T [A]를 T [B]로 변환합니다.
모나드는 이해하기 어려운 이해와 여러 은유를 가진 신화적인 생물이지만, 응용 기능을 얻으면 이해하기가 꽤 쉽다는 것을 알았습니다.
Functor allow us to apply functions to things in a context. But what if the functions we want to apply are already in a context? (And is pretty easy to end in that situation if you have functions that take more than one parameter).
Now we need something like a Functor but that also takes functions already in the context and applies them to elements in the context. And that's what the applicative functor is. Here is the signature:
trait Applicative[T[_]] extends Functor[T]{
def pure[A](a:A):T[A]
def <*>[A,B](tf:T[A=>B])(ta:T[A]):T[B]
}
So far so good. Now comes the monads: what if now you have a function that puts things in the context? It's signature will be g:X=>M[X] ... you can't use a functor because it expects X=>Y so we'll end with M[M[X]], you can't use the applicative functor because is expecting the function already in the context M[X=>Y] .
So we use a monad, that takes a function X=>M[X] and something already in the context M[A] and applies the function to what's inside the context, packing the result in only one context. The signature is:
trait Monad[M[_]] extends Applicative[M]{
def >>=[A,B](ma:M[A])(f:A=>M[B]):M[B]
}
It can be pretty abstract, but if you think on how to work with "Option" it shows you how to compose functions X=>Option[X]
EDIT: Forgot the important thing to tie it: the >>= symbol is called bind and is flatMap in Scala. (Also, as a side note, there are some laws that functors, applicatives, and monads have to follow to work properly).
The best article laying out in details those two notions is "The Essence of the Iterator Pattern " from Eric Torreborre's Blog.
Functor
trait Functor[F[_]] {
def fmap[A, B](f: A => B): F[A] => F[B]
}
- One way of interpreting a
Functor
is to describe it as a computation of values of typeA
.
For example:
List[A]
is a computation returning several values of typeA
(non-deterministic computation),Option[A]
is for computations that you may or may not have,Future[A]
is a computation of a value of typeA
that you will get later, and so on.- Another way of picturing it is as some kind of "container" for values of type A.
It is the basic layer from which you define:
PointedFunctor
(to create a value of typeF[A]
) andApplic
(to provide a methodapplic
, being a computed value inside the containerF (F[A => B])
, to apply to a valueF[A]
),Applicative Functor
(aggregation of anApplic
and aPointedFunctor
).
All three elements are used to define a Monad
.
I think this great blog post will help you first for monad
. http://blog.enfranchisedmind.com/2007/08/a-monad-tutorial-for-ocaml/
참고URL : https://stackoverflow.com/questions/8460594/scala-functor-and-monad-differences
'Development Tip' 카테고리의 다른 글
클래스에서 정적 메서드를 언제 사용해야하며 이점은 무엇입니까? (0) | 2020.11.27 |
---|---|
실행중인 Amazon ec2 인스턴스를 예약하는 방법은 무엇입니까? (0) | 2020.11.27 |
Git에서 분기의 해시를 찾는 방법은 무엇입니까? (0) | 2020.11.27 |
탭 / 브라우저 닫기 전 확인 (0) | 2020.11.27 |
클래스의 Python 검사 인스턴스 (0) | 2020.11.27 |