문제

알아요 newtype 더 자주 비교됩니다 data Haskell에서는 기술적 인 문제보다 더 많은 디자인 시점 에서이 비교를 제기하고 있습니다.

Imperitive/OO 언어에는 반란이 있습니다. "원시적 집착"원시 유형을 많이 사용하면 프로그램의 유형 안전성을 줄이고 동일한 유형 값의 실수로 상호 교환 가능성을 소개합니다. 그렇지 않으면 다른 목적을위한 의도가 있습니다. 예를 들어 많은 것들이 줄이 될 수 있지만 컴파일러는 정적으로 알 수 있습니다. 이는 이름이라는 의미이며 주소로 도시가된다는 의미입니다.

그래서 얼마나 자주, Haskell 프로그래머는 newtype 다른 원시적 값에 유형 차별을 제공하려면? 사용 type 별칭을 소개하고 프로그램의 가독성이 명확한 의미를 제공하지만 실수로 값의 교환을 방지하지는 않습니다. Haskell을 배우면서 유형 시스템이 내가 만나는 것만 큼 강력하다는 것을 알 수 있습니다. 그러므로 나는 이것이 자연스럽고 일반적인 관행이라고 생각하지만, 나는 newtype 이 빛에서.

물론 많은 프로그래머가 다르게 일을하지만, 이것이 Haskell에서 전혀 공통적입니까?

도움이 되었습니까?

해결책

NewTypes의 주요 용도는 다음과 같습니다.

  1. 유형에 대한 대체 인스턴스를 정의합니다.
  2. 선적 서류 비치.
  3. 데이터/형식 정확성 보증.

나는 NewTypes를 광범위하게 사용하는 신청서를 진행하고 있습니다. newtypes Haskell에서는 순전히 컴파일 타임 개념입니다. 예를 들어 아래의 Unprappers와 함께 unFilename (Filename "x") "x"와 동일한 코드로 컴파일되었습니다. 런 타임 히트가 절대적으로 없습니다. 함께 있습니다 data 유형. 이것은 위의 나열된 목표를 달성하는 아주 좋은 방법입니다.

-- | A file name (not a file path).
newtype Filename = Filename { unFilename :: String }
    deriving (Show,Eq)

실수로 이것을 파일 경로로 취급하고 싶지 않습니다. 파일 경로가 아닙니다. 데이터베이스 어딘가에 개념적 파일의 이름입니다.

알고리즘이 올바른 것을 언급하는 것이 매우 중요합니다. NewTypes는 이것에 도움이됩니다. 예를 들어, 웹 애플리케이션에 파일 업로드를 고려하는 것도 매우 중요합니다. 이 유형이 있습니다.

-- | A sanitized (safe) filename.
newtype SanitizedFilename = 
  SanitizedFilename { unSafe :: String } deriving Show

-- | Unique, sanitized filename.
newtype UniqueFilename =
  UniqueFilename { unUnique :: SanitizedFilename } deriving Show

-- | An uploaded file.
data File = File {
   file_name     :: String         -- ^ Uploaded file.
  ,file_location :: UniqueFilename -- ^ Saved location.
  ,file_type     :: String         -- ^ File type.
  } deriving (Show)

업로드 된 파일에서 파일 이름을 정리하는이 기능이 있다고 가정합니다.

-- | Sanitize a filename for saving to upload directory.
sanitizeFilename :: String            -- ^ Arbitrary filename.
                 -> SanitizedFilename -- ^ Sanitized filename.
sanitizeFilename = SanitizedFilename . filter ok where 
  ok c = isDigit c || isLetter c || elem c "-_."

이제 그로부터 독특한 파일 이름을 생성합니다.

-- | Generate a unique filename.
uniqueFilename :: SanitizedFilename -- ^ Sanitized filename.
               -> IO UniqueFilename -- ^ Unique filename.

임의의 파일 이름에서 독특한 파일 이름을 생성하는 것은 위험합니다. 먼저 소독해야합니다. 마찬가지로, 독특한 파일 이름은 항상 확장에 따라 안전합니다. 파일을 지금 디스크에 저장하고 원하는 경우 해당 파일 이름을 데이터베이스에 넣을 수 있습니다.

그러나 많이 마무리/풀어야한다는 것은 성가신 일 수 있습니다. 장기적으로, 나는 특히 가치 불일치를 피하는 데 가치가 있다고 생각합니다. ViewPatterns는 다소 도움이됩니다.

-- | Get the form fields for a form.
formFields :: ConferenceId -> Controller [Field]
formFields (unConferenceId -> cid) = getFields where
   ... code using cid ..

어쩌면 함수에서 랩핑을 풀고 문제가 발생한다고 말할 수 있습니다. 통과하면 어떻게 될까요? cid 잘못된 기능으로? 문제가되지 않으면 컨퍼런스 ID를 사용하는 모든 기능은 ConferenceID 유형을 사용합니다. 출현하는 것은 컴파일 시간에 강제로 제공되는 일종의 기능-기능 수준 계약 시스템입니다. 꽤 좋은. 그렇습니다. 특히 큰 시스템에서 가능한 한 자주 사용합니다.

다른 팁

나는 이것이 대부분 상황의 문제라고 생각합니다.

PathNames를 고려하십시오. 표준 사전 사전에는 편의상 모든 문자열 및 목록 작업에 액세스하기를 원하기 때문에 "Type FilePath = String"이 있습니다. "NewType FilePath = FilePath String"이 있으면 FilePathLength, FilePathMap 등이 필요하거나 전환 기능을 영원히 사용하게됩니다.

반면에 SQL 쿼리를 고려하십시오. SQL 주입은 일반적인 보안 구멍이므로와 같은 것을 갖는 것이 합리적입니다.

newtype Query = Query String

그런 다음 견적 문자를 피하여 문자열을 쿼리 (또는 쿼리 조각)로 변환하는 추가 기능을 추가하거나 같은 방식으로 템플릿의 공백을 채우십시오. 이렇게하면 견적 이스케이프 함수를 거치지 않고 실수로 사용자 매개 변수를 쿼리로 변환 할 수 없습니다.

간단합니다 X = Y 선언, type 문서화입니다. newtype 유형 검사입니다. 이는 이유 newtype 비교됩니다 data.

나는 상당히 자주 사용합니다 newtype 다른 유형과 같은 방식으로 저장 (그리고 종종 조작 된)이 다른 것과 혼동되지 않도록하는 목적을 위해서만 설명합니다. 그런 식으로 약간 더 효율적으로 작동합니다. data 선언; 다른 하나를 선택해야 할 특별한 이유는 없습니다. GHC와 함께하십시오 GeneralizedNewtypeDeriving 확장자는 다음과 같은 클래스를 자동으로 도출 할 수 있습니다. Num, 온도 나 엔화가 당신이 할 수있는대로 추가 및 차감을 허용합니다. IntS 또는 그 아래에있는 것이 무엇이든. 그러나 이것에 대해 조금 조심하기를 원합니다. 일반적으로 하나는 온도에 다른 온도를 곱하지 않습니다!

이러한 것들이 얼마나 자주 사용되는지에 대한 아이디어를 위해, 내가 지금하고있는 합리적으로 큰 프로젝트에서 약 122 개의 사용이 있습니다. data, 39 사용 newtype, 및 96 사용 type.

그러나 "간단한"유형에 관한 한 비율은 96 개의 사용 중 32 개가 type 실제로 기능 유형에 대한 별명입니다

type PlotDataGen t = PlotSeries t -> [String]

여기에 두 가지 추가 복잡성이 있습니다. 첫째, 실제로는 단순한 기능 유형입니다. X = Y 별칭, 두 번째는 매개 변수화되어 있습니다. PlotDataGen 다른 유형에 적용하여 다음과 같은 새 유형을 만드는 유형 생성자입니다. PlotDataGen (Int,Double). 이런 종류의 일을 시작하면 type 더 이상 문서화가 아니라 실제로는 데이터 수준이 아닌 유형 수준에서 기능입니다.

newtype 때때로 어디에서 사용됩니다 type 재귀 유형 정의가 필요한 곳과 같이 될 수는 없지만, 이것이 합리적으로 드물다는 것을 알 수 있습니다. 따라서이 특정 프로젝트에서 최소한 내 "원시"유형 정의의 약 40%가 newtypeS와 60%가 있습니다 type에스. 몇 가지 newtype 정의는 유형이었고, 당신이 언급 한 정확한 이유로 확실히 변환되었습니다.

요컨대, 그렇습니다. 이것은 빈번한 관용구입니다.

사용하는 것이 일반적이라고 생각합니다 newtype 유형 구분. 많은 경우에 이것은 다른 유형의 클래스 인스턴스를 제공하거나 구현을 숨기고 싶지만 우발적 인 전환으로부터 보호하기를 원하기 때문입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top