하스켈에서 "리프팅"이란 무엇입니까?
나는 "리프팅"이 무엇인지 이해하지 못한다. "리프트"가 무엇인지 이해하기 전에 모나드를 먼저 이해해야합니까? (모나드에 대해서도 완전히 무지합니다 :) 아니면 누군가 간단한 단어로 설명 할 수 있습니까?
리프팅은 수학적 개념보다 디자인 패턴에 가깝습니다. (여기서는 주변 사람들이 리프트가 카테고리 또는 어떤 방식인지 보여줌으로써 나를 반박 할 것으로 예상하지만).
일반적으로 매개 변수가있는 일부 데이터 유형이 있습니다. 같은 것
data Foo a = Foo { ...stuff here ...}
Foo
숫자 유형 ( Int
, Double
등)을 많이 사용 하고 이러한 숫자를 풀고, 더하거나 곱한 다음 다시 랩핑하는 코드를 계속 작성해야 한다고 가정하십시오 . 랩핑 해제 랩 코드를 한 번 작성하여이를 단락시킬 수 있습니다. 이 기능은 전통적으로 "리프트"라고합니다.
liftFoo2 :: (a -> b -> c) -> Foo a -> Foo b -> Foo c
즉, (+)
연산자 와 같은 2 인수 함수 를 사용하여 Foos에 해당하는 함수로 바꾸는 함수가 있습니다.
이제 쓸 수 있습니다
addFoo = liftFoo2 (+)
편집 : 추가 정보
당신은 물론 수 liftFoo3
, liftFoo4
등등. 그러나 이것은 종종 필요하지 않습니다.
관찰로 시작
liftFoo1 :: (a -> b) -> Foo a -> Foo b
그러나 그것은 정확히 동일합니다 fmap
. 그래서 liftFoo1
당신이 쓰는 것보다
instance Functor Foo where
fmap foo = ...
완전한 규칙 성을 원한다면 말할 수 있습니다.
liftFoo1 = fmap
Foo
functor로 만들 수 있다면 아마도 functor로 만들 수 있습니다. 실제로 작성할 수 있으면 liftFoo2
적용 인스턴스는 다음과 같습니다.
import Control.Applicative
instance Applicative Foo where
pure x = Foo $ ... -- Wrap 'x' inside a Foo.
(<*>) = liftFoo2 ($)
(<*>)
Foo 의 연산자는 다음과 같은 유형입니다.
(<*>) :: Foo (a -> b) -> Foo a -> Foo b
랩핑 된 기능을 랩핑 된 값에 적용합니다. 따라서 구현할 수 있다면 liftFoo2
이것을 관점에서 작성할 수 있습니다. 또는 모듈에 포함되어 liftFoo2
있기 때문에 직접 구현할 수 있습니다.Control.Applicative
liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c
마찬가지로있다 liftA
및 liftA3
. 그러나 다른 연산자가 있기 때문에 실제로 자주 사용하지는 않습니다.
(<$>) = fmap
이것은 당신이 쓸 수 있습니다 :
result = myFunction <$> arg1 <*> arg2 <*> arg3 <*> arg4
이 용어 myFunction <$> arg1
는 Foo로 래핑 된 새 함수를 반환합니다. 이것은 차례로 다음을 사용하여 다음 인수에 적용될 수 있습니다 (<*>)
. 따라서 이제는 모든 arity에 대해 리프트 기능을 사용하는 대신 데이지 체인을 사용합니다.
바울과 야 이르 쿠는 모두 좋은 설명입니다.
들어 올리는 함수는 임의의 수의 인수를 가질 수 있으며 동일한 유형일 필요는 없다고 덧붙이고 싶습니다. 예를 들어 liftFoo1을 정의 할 수도 있습니다.
liftFoo1 :: (a -> b) -> Foo a -> Foo b
일반적으로 1 개의 인수를 취하는 함수의 리프팅은 type 클래스에서 캡처되며 Functor
리프팅 작업은 fmap
다음과 같습니다.
fmap :: Functor f => (a -> b) -> f a -> f b
liftFoo1
의 유형 과의 유사성을 주목하십시오 . 실제로, 가지고 있다면 다음과 같은 인스턴스를 liftFoo1
만들 수 있습니다 .Foo
Functor
instance Functor Foo where
fmap = liftFoo1
또한 임의의 수의 인수로 승화하는 일반화를 적용 스타일 이라고 합니다 . 고정 된 수의 인수로 함수의 리프팅을 파악할 때까지이 작업에 신경 쓰지 마십시오. 그러나 당신이 할 때 , Haskell 이 이것에 대해 좋은 장을 가지고 있음을 배우십시오 . Typeclassopedia는 설명 또 다른 좋은 문서입니다 은 Functor 및 실용적 (뿐만 아니라 다른 종류의 클래스를, 스크롤 해당 문서의 오른쪽 장에 이르기까지).
도움이 되었기를 바랍니다!
예제로 시작해 보겠습니다 (더 명확한 표현을 위해 공백이 추가됨).
> import Control.Applicative
> replicate 3 'a'
"aaa"
> :t replicate
replicate :: Int -> b -> [b]
> :t liftA2
liftA2 :: (Applicative f) => (a -> b -> c) -> (f a -> f b -> f c)
> :t liftA2 replicate
liftA2 replicate :: (Applicative f) => f Int -> f b -> f [b]
> (liftA2 replicate) [1,2,3] ['a','b','c']
["a","b","c","aa","bb","cc","aaa","bbb","ccc"]
> ['a','b','c']
"abc"
liftA2
일반 유형의 함수 를 목록 등과 같은에 래핑 된 동일한 유형Applicative
의 함수로 변환합니다 IO
.
Another common lift is lift
from Control.Monad.Trans
. It transforms a monadic action of one monad to an action of a transformed monad.
In general, "lift" lifts a function/action into a "wrapped" type (so the original function gets to work "under the wraps").
The best way to understand this, and monads etc., and to understand why they are useful, is probably to code and use it. If there's anything you coded previously that you suspect can benefit from this (i.e. this will make that code shorter, etc.), just try it out and you'll easily grasp the concept.
Lifting is a concept which allows you to transform a function into a corresponding function within another (usually more general) setting
take a look at http://haskell.org/haskellwiki/Lifting
According to this shiny tutorial, a functor is some container (like Maybe<a>
, List<a>
or Tree<a>
that can store elements of some another type, a
). I have used Java generics notation, <a>
, for element type a
and think of the elements as berries on the tree Tree<a>
. There is a function fmap
, which takes an element conversion function, a->b
and container functor<a>
. It applies a->b
to every element of the container effectively converting it into functor<b>
. When only first argument is supplied, a->b
, fmap
waits for the functor<a>
. That is, supplying a->b
alone turns this element-level function into the function functor<a> -> functor<b>
that operates over containers. This is called lifting of the function. Because the container is also called a functor, the Functors rather than Monads are a prerequisite for the lifting. Monads are sort of "parallel" to lifting. Both rely on the Functor notion and do f<a> -> f<b>
. The difference is that lifting uses a->b
for the conversion whereas Monad requires the user to define a -> f<b>
.
참고URL : https://stackoverflow.com/questions/2395697/what-is-lifting-in-haskell
'IT박스' 카테고리의 다른 글
너무 오래 걸리는 SQL Server Broker 사용 (0) | 2020.07.04 |
---|---|
파이썬 : 두 절대 경로를 비교하여 상대 경로 얻기 (0) | 2020.07.03 |
GNU Make에서 CPPFLAGS와 CXXFLAGS의 차이점 (0) | 2020.07.03 |
지원 라이브러리에서 PreferenceActivity로 작업 표시 줄을 추가하는 방법은 무엇입니까? (0) | 2020.07.03 |
bash if / else 문에서 파일 grep 비교를 어떻게 사용합니까? (0) | 2020.07.03 |