2017-03-27 2 views
2

하스켈에는 제품 유형이 있으며 튜플이 있습니다.하스켈의 제품 유형 및 튜플에 대한 중복

전용 유형을 값과 연관시키지 않으려면 튜플을 사용하고, 원하는 경우에는 제품 유형을 사용할 수 있습니다.

그러나 나는 중복 제품 종류의 표기

data Foo = Foo (String, Int, Char) 
data Bar = Bar String Int Char 

왜 표기법의 두 종류가 있습니다 거기 느낌? 당신이 다른 것을 선호하는 경우가 있습니까?

튜플을 사용할 때 레코드 표기법을 사용할 수없는 것 같지만 이는 단지 편리한 문제 일뿐입니다. 또 다른 것은 제품 유형과 달리 튜플에서의 주문 개념 일 수도 있지만, 그 이유는 함수의 이름이 fstsnd 일 뿐이라고 생각합니다.

답변

0

Foo에 자주 사용되는 패턴을 기대하지 않습니다. 생성자가 다음과 같이 약간의 차이가 있습니다 : Bar :: String -> Int -> Char -> Bar과 대조적으로 Foo :: (String, Int, Char) -> Foo. 그렇다면 Foo undefinedFoo (undefined, ..., ...)은 엄밀히는 다른 것들을 말하는 반면, Bar에서는 하나의 정의되지 않은 수준을 놓치고 있습니다.

4

유형

data Foo = Foo (String, Int, Char) 

는 배정 해제 튜플을 나타낸다. 값은 다음과 같이 구성됩니다.

undefined 
Foo undefined 
Foo (undefined, undefined, undefined) 
etc. 

이것은 일반적으로 골칫거리입니다. 이 때문에 실제 코드에서 이러한 정의를 보는 것은 드뭅니다. 우리 중 하나는 일반 데이터 유형

data Foo = Foo String Int Char 

이상이 newtype

newtype Foo = Foo (String, Int, Char) 

newtype 사용하기 그냥 불편할 수 있지만, 적어도 더블 리프트를하지 튜플을 수행합니다 undefinedFoo undefined이를 이제는 동일한 값.

newtype도 일반 튜플과 Foo 사이에서 양방향으로 0이 아닌 변환을 제공합니다.

이러한 newtype이 사용 중입니다. 프로그래머가 이미 튜플과 연결된 유형의 클래스에 대해 다른 인스턴스를 필요로 할 때. 또는 아마도 "스마트 생성자"관용구에 사용됩니다.

7

@chi's answer은 하스켈의 평가 모델과 관련하여 기술적 인 차이점이 있습니다. 이런 형식의 프로그래밍 철학에 대한 통찰력을 얻기를 바랍니다.

카테고리 이론에서 우리는 일반적으로 "동형에 이르기까지"객체를 사용합니다. Bar은 물론 (String, Int, Char)과 동형이기 때문에 범주적인 관점에서 볼 때 똑같습니다. 어떤 의미에서 튜플

bar_tuple :: Iso' Bar (String, Int, Char) 
bar_tuple = iso to from 
    where to (Bar s i c) = (s, i, c) 
      from (s, i, c) = Bar s i c 

은 그들이 서로 다른 값들의 집합 인 외의 의미가없고, 제품 유형의 플라톤 형태이다.다른 모든 제품 유형은 평범한 오래된 튜플에서 매핑 될 수 있습니다.

모든 하스켈 유형이 궁극적으로 제품 합계로 내려갈 때 왜 모든 곳에서 튜플을 사용하지 않습니까? 그것은 의사 소통에 관한 것입니다. Martin Fowler가 말한 것처럼,

바보는 컴퓨터가 이해할 수있는 코드를 작성할 수 있습니다. 좋은 프로그래머는 인간이 이해할 수있는 코드를 작성합니다.

이름이 중요합니다.

data Customer = Customer { name :: String, address :: String } 

같은 사용자 정의 제품 유형을 작성하는 것은 그냥 "두 문자열"을 의미 (String, String) 달리 코드를 읽는 사람에게 의미 와 유형 Customer, 불어 넣는다. 당신이 NonEmpty 생성자를 수출하지 않는 경우, 지금

newtype NonEmpty a = NonEmpty [a] 

nonEmpty :: [a] -> Maybe (NonEmpty a) 
nonEmpty [] = Nothing 
nonEmpty xs = Just (NonEmpty xs) 

당신이 할 수있는 : 당신은 데이터의 표현을 숨기고 스마트 생성자를 사용하여 불변을 적용 할 때

사용자 정의 유형은 특히 유용 사람들이 스마트 생성자 nonEmpty을 통과하도록합니다. 누군가가 NonEmpty 값을 건네면 적어도 하나 이상의 요소가 있다고 가정 할 수 있습니다.

당신은에 Customer를 변환하는 지금 싼 것을 제외하고 그러나 이것은 정말 많이 구입하지 않는

newtype Customer = Bar (String, String) 
name, address :: Customer -> String 
name (Customer (n, a)) = n 
address (Customer (n, a)) = a 

물론 후드 튜플로 Customer을 대표하고 evocatively 이름의 필드 접근에 노출 될 수 있습니다 터플 (터플 지향 API로 작동하는 성능에 민감한 코드를 작성하는 경우).

코드가 특정 문제 (코드 작성의 전체 요점)를 해결하기위한 것이라면 문제를 해결할뿐만 아니라 해결 한 것처럼 보일 수도 있습니다. 어떤 사람 - 아마도 2 년 안에 -이 코드를 읽고 이해해야합니다. 사전 지식 작동 방식에 대한 지식이 있어야합니다. 사용자 정의 유형은 이와 관련하여 매우 중요한 커뮤니케이션 도구입니다.