2013-02-09 1 views
0

다음 코드의 경우 storePhone 함수가 Int를 저장하는 전화 번호 유형 (HomePhone 또는 WorkPhone)을 어떻게 지정합니까?대수 데이터 형식에서 유형 동의어를 사용하는 방법은 무엇입니까?

type HomePhone = Int 
type WorkPhone = Int 

data Phone = HomePhone 
      | WorkPhone 

storePhone :: int -> Phone 
storePhone num = num 

main :: IO() 
main = print $ storePhone 12345678 

이 질문은 내가 수행중인 부수 프로젝트에 대한 간단한 질문이었습니다. 파일을 관련 데이터 형식 (예 : 전화 유형 샘플)으로 구문 분석하는 모듈이 있습니다. 모든 데이터는 Double이지만 다른 의미 론적 의미가 있습니다. 다른 모듈에서는 데이터를 사용하는 메소드가 있습니다. 각 메서드는 데이터 형식 (HomePhone, WorkPhone이라고도 함)의 다른 순열을 인수로 사용합니다. HomePhone과 WorkPhone 데이터 형식 또는 심지어 newtype을 만들 수도 있었지만 데이터를 사용한 메서드가 패턴 매칭과 물건을 많이 사용하여 더러워 보일 수있었습니다. 그래서 좀 더 우아하고 안전하게 입력 할 수 있도록 데이터 유형 (일명 전화)을 단순화 할 수 있는지 궁금합니다. 건배! 다음과 같이해야할까요?

type HomePhone = Int 
type WorkPhone = Int 

data Phone = HomePhone HomePhone 
      | WorkPhone WorkPhone 
+2

컴파일도 되니? 컴파일러는 오류 및 경고에서 유용한 정보를 많이 줄 수 있습니다. – Yuras

답변

4

현재 양식에서 Phone 유형은 전화 번호를 저장할 수 없습니다. 그것은 두 개의 생성자를 가지고 있는데, 둘 다 제로 인수를 가지므로 아무 것도 저장할 수 없습니다. 생성자의 이름이 이전에 정의한 유형 이름과 동일하다는 사실은 아무런 의미가 없습니다.

당신은 아마이 같은 목적 :

type PhoneNumber = String -- Storing phone numbers as ints is a bad idea 

data PhoneType = HomePhone 
       | WorkPhone 
       deriving Show 

data Phone = Phone PhoneType PhoneNumber 
      deriving Show 

storePhone :: PhoneNumber -> PhoneType -> Phone 
storePhone number typ = Phone typ number 

main :: IO() 
main = print $ storePhone "12345678" HomePhone 
4

내가 sepp2k 아주 잘 당신의 질문에 대답 생각을하지만 난 당신이 처음부터 문제가 있다고 생각하는 이유를 설명하려고합니다. 유형과 값 사이에는 유형 생성자와 값 생성자 사이에는 차이가 있습니다.

Phone = Phone 

이 예제에서 왼쪽은 유형이고 오른쪽은 값입니다. 형식과 값은 모두 같은 이름을 가질 수 있습니다. 컴파일러는 당신이 의미하는 것을 알아낼 것입니다. 기본적으로 타입 선언과 데이터 선언에서는 타입을 의미하고, 함수 구현에서는 값을 의미합니다. 이 예에서

Phone = NoPhone 
     | Phone Int 

, NoPhone는 값이며, 그 값을 입력하도록 Int의 값을 취하고 있기 때문에 오른쪽 Phone는 값 생성자이다. 왼쪽 편은 여전히 ​​유형입니다. 이 경우 유형 Container Int 것 -이 예에서
Container a = NotEmpty a 
      | Empty 

, Container 당신이 그것을 같은 유형의 종류를 얻을 수있는 Int을 줄 수 있기 때문에, 타입 생성자이다. Empty은 값이고 NotEmpty은 값 생성자이며 a에 대해 선택하는 모든 유형의 값을 취합니다. T을 호출하여 Container T 값을 생성합니다.

예제에서 유형 및 값의 개념을 혼합합니다.

type HomePhone = Int 
type WorkPhone = Int 

HomePhoneWorkPhone 그냥 다른 이름이 유형 Phone의 아무것도 값 HomePhone 또는 값 WorkPhone 하나를 가지고 있다고 말한다 유형 Int

data Phone = HomePhone 
      | WorkPhone 

에 대한 것을 말한다. 중요하게도이 값은 이전에 선언 한 같은 이름의 동의어와 동일하지 않습니다.

storePhone :: int -> Phone 

은 storePhone 유형 Int의 값을 취 입력 Phone의 값을 반환하는 것을 말한다.

storePhone num = num 

이것은 문제입니다. 이 줄에서 num은 Int 유형의 값이지만 num을 반환하고 형식 선언에서 HomePhone 또는 WorkPhone 값인 Phone 유형의 값을 반환한다고 말한 것입니다. 바보가되고 싶지만 타입 선언을 준수한다면, 할 수있다

storePhone num = if num > 0 then HomePhone else WorkPhone -- silly, but compiles :) 
관련 문제