fmap이있을 때 Haskell에서지도의 요점은 무엇입니까?


97

내가 사용 해봤 모든 곳 map, fmap잘으로 일했다. Haskell의 제작자는 왜 map함수 의 필요성을 느꼈 습니까? 그냥 현재로 알려진이 될 수 없습니다 fmapfmap언어에서 제거 할 수 있을까?


11
나는 당신이 '하스켈에서 fmap의 요점이 무엇인지'라고 묻는 것 같아요?
zw324

11
요점이 무엇인지 압니다 fmap. Functor 인스턴스에 함수를 매핑하는 것입니다. .NET 전문화의 목적이 무엇인지 궁금합니다 map.
Clark Gaebel 2011

답변:


95

augustss의 댓글에 관심을 수있는 답변을하고 싶습니다 .

그것은 실제로 일어나는 방식이 아닙니다. 무슨 일이 있었는지 맵의 유형이 Haskell 1.3의 Functor를 포함하도록 일반화되었습니다. 즉, Haskell 1.3에서는 fmap을 map이라고했습니다. 이 변경 사항은 Haskell 1.4에서 되돌려졌으며 fmap이 도입되었습니다. 이러한 변화의 이유는 교육적이었습니다. 초보자에게 하스켈을 가르 칠 때 매우 일반적인 유형의지도는 오류 메시지를 이해하기 더 어렵게 만들었습니다. 제 생각에는 이것은 문제를 해결하는 올바른 방법이 아닙니다.

Haskell 98은 일부 Haskeller (나 포함)에 의해 한 단계 뒤로 물러 난 것으로 간주되며, 이전 버전은보다 추상적이고 일관된 라이브러리를 정의했습니다. 오 잘.


16
이러한 역방향 단계는 어디서나 수집되고 문서화됩니까? 더 나은 해결책이 있는지 확인하는 것도 흥미로울 것입니다.
Davorak 2011

3
이는 map and fmap오랫동안 사용되어 왔으며 2006 년 8 월 Haskell-prime 메일 링리스트에서 재가열되었습니다 -haskell.org/pipermail/haskell-prime/2006-August/thread.html . 대위법으로 나는 현상 유지를 선호합니다. 나에게는 Miranda에 해당하는 Haskell의 하위 집합이 있다는 것이 가치있는 것 같습니다. 영국에서 Miranda는 컴퓨터 과학 학생뿐만 아니라 수학 학생을위한 교육 언어로 사용되었습니다. 기능이없는 언어 (예 : Mathematica)가 그 틈새 시장을 잃지 않았다면 하스켈을 통일 된 map채운다 고 보지 않습니다 .
stephen tetley 2011

35
그리고 저는 이미 알지 못하는 사람을 위해 8 월은 하스켈이 존재하기 전부터 모든 실용적인 목적을 위해 하스켈 커뮤니티의 일원이 된 레나 트 어거스트 슨이라는 사실을 알고 싶습니다. A History of Haskell , 그래서 문제의 코멘트는 어떤 식 으로든 간접적 인 소문이 아닙니다!
CA McCann 2011

3
지금이 Nitpicks 페이지에 이 문제가 언급 하스켈 위키는.
Alexey

내가 Haskell을 배울 때 항상 fmap과 flatmap을 혼동했기 때문에이 결정이 교육적인 이유로 내려진 것은 재밌습니다. 그들은 n00b 포커스 그룹을 함께 얻었어야합니다. :)
Danny Andrews

27

https://wiki.haskell.org/Typeclassopedia#FunctorFunctor문서에서 인용

별도의 map기능이 필요한 이유를 물어볼 수 있습니다 . 현재 목록 전용 map기능을 없애고 대신 이름 fmap을 변경 하지 않는 이유는 무엇 map입니까? 음, 좋은 질문입니다. 일반적인 주장은 방금 Haskell을 배우는 사람이 map잘못 사용 하면 about보다 목록에 대한 오류를 보게 될 것이라는 것 Functor입니다.


1
이것은 나에게 많은 의미가 있습니다.
hbobenicio

25

응용 프로그램 사이트에서는 동일하게 보이지만 물론 다릅니다. 당신이 그 두 가지 기능 중 하나에 적용하면 map또는 fmap값 목록에, 그들은 동일한 결과를 생성하지만 그는이 같은 목적을 위해 의미있는 것은 아닙니다.

GHCI 세션 (Glasgow Haskell Compiler Interactive)을 실행하여이 두 함수에 대한 정보를 쿼리 한 다음 구현을 살펴보면 많은 차이점을 발견하게됩니다.

지도

GHCI에 대한 정보를 쿼리하십시오. map

Prelude> :info map
map :: (a -> b) -> [a] -> [b]   -- Defined in ‘GHC.Base’

모든 유형 a의 값 목록을 생성하는 모든 유형의 값 목록에 적용 할 수있는 고차 함수로 정의 된 것을 볼 수 b있습니다. (다형이지만 ab모든 유형의 상기 정의 스탠드로) map기능이 적용되도록 의도 값에서 하스켈 많은 사람들 중에서 단지 하나의 가능한 데이터 형식이다. map값 목록이 아닌 항목 에는 함수를 적용 할 수 없습니다.

GHC.Base 소스 코드 에서 읽을 수 있듯이 map함수는 다음과 같이 구현됩니다.

map _ []     = []
map f (x:xs) = f x : map f xs

패턴 일치를 사용 하여 목록 x의 꼬리 (the xs) 에서 머리 (the )를 빼낸 다음 :(cons) 값 생성자 를 사용하여 새 목록을 구성하여 앞에 추가합니다 f x( "f에 적용됨" 로 읽음 ). map목록이 비워 질 때까지 꼬리 위로 의 재귀에 . map함수 의 구현은 다른 함수에 의존하지 않고 그 자체에만 의존 한다는 점은 주목할 가치가 있습니다.

fmap

이제에 대한 정보를 쿼리 fmap하면 매우 다른 것을 볼 수 있습니다.

Prelude> :info fmap
class Functor (f :: * -> *) where
  fmap :: (a -> b) -> f a -> f b
  ...
  -- Defined in ‘GHC.Base’

이 시간 fmapFunctor유형 클래스 에 속하려는 데이터 유형에 의해 구현이 제공되어야하는 함수 중 하나로 정의됩니다 . 이는 함수에 대한 구현을 제공 할 수있는 "값 목록" 데이터 유형 뿐만 아니라 둘 이상의 데이터 유형이있을 수 있음을 의미합니다 fmap. 이는 fmap훨씬 더 큰 데이터 유형 집합에 적용 할 수 있습니다. 실제로 펑터입니다!

GHC.Base 소스 코드 에서 읽을 수 있듯이 fmap함수 의 가능한 구현은 Maybe데이터 유형에서 제공하는 것입니다 .

instance  Functor Maybe  where
  fmap _ Nothing       = Nothing
  fmap f (Just a)      = Just (f a)

다른 가능한 구현은 2- 튜플 데이터 유형에서 제공하는 것입니다.

instance Functor ((,) a) where
  fmap f (x,y) = (x, f y)

또 다른 가능한 구현은 목록 데이터 유형 (물론!)에서 제공하는 것입니다.

instance  Functor []  where
  fmap f xs = map f xs

map기능에 의존 합니다.

결론

map반면 함수 (값은 어떤 타입 인) 값들의 목록에 불과에 적용 할 수있는 fmap기능은 훨씬 더 많은 데이터 타입을 적용 할 수있는 다음 펑 클래스에 속하는 것들 (예 괜찮은 남자 튜플,리스트 등의 모든 ). 이후 "값에서" 다음 (그것의 구현을 제공하기 때문에), 데이터 타입은 펑이기도 fmap뿐만 아니라 매우 동일한 결과를 생산에 적용될 수있다 map.

map  (+3) [1..5]
fmap (+3) (Just 15)
fmap (+3) (5, 7)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.