IT박스

하스켈에서 "리프팅"이란 무엇입니까?

itboxs 2020. 7. 3. 20:42
반응형

하스켈에서 "리프팅"이란 무엇입니까?


나는 "리프팅"이 무엇인지 이해하지 못한다. "리프트"가 무엇인지 이해하기 전에 모나드를 먼저 이해해야합니까? (모나드에 대해서도 완전히 무지합니다 :) 아니면 누군가 간단한 단어로 설명 할 수 있습니까?


리프팅은 수학적 개념보다 디자인 패턴에 가깝습니다. (여기서는 주변 사람들이 리프트가 카테고리 또는 어떤 방식인지 보여줌으로써 나를 반박 할 것으로 예상하지만).

일반적으로 매개 변수가있는 일부 데이터 유형이 있습니다. 같은 것

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

Foofunctor로 만들 수 있다면 아마도 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

마찬가지로있다 liftAliftA3. 그러나 다른 연산자가 있기 때문에 실제로 자주 사용하지는 않습니다.

(<$>) = 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만들 수 있습니다 .FooFunctor

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

반응형