수색…


기본 구문

레코드는 필드 이름을 지정할 수있는 sum algebraic data 형식의 확장입니다.

data StandardType = StandardType String Int Bool --standard way to create a sum type

data RecordType = RecordType { -- the same sum type with record syntax
    aString :: String
  , aNumber :: Int
  , isTrue  :: Bool
  }

그런 다음 필드 이름을 사용하여 레코드에서 명명 된 필드를 가져올 수 있습니다

> let r = RecordType {aString = "Foobar", aNumber= 42, isTrue = True}
> :t r
  r :: RecordType
> :t aString
  aString :: RecordType -> String
> aString r
  "Foobar"

레코드는 패턴 일치와 일치 할 수 있습니다.

case r of
  RecordType{aNumber = x, aString=str} -> ... -- x = 42, str = "Foobar"

모든 필드의 이름을 지정할 필요는 없습니다.

레코드는 필드 이름을 지정하여 만들지 만 일반 합계 유형으로 만들 수도 있습니다 (필드 수가 적고 변경할 가능성이없는 경우에 유용 할 때가 많습니다)

r  = RecordType {aString = "Foobar", aNumber= 42, isTrue = True}
r' = RecordType  "Foobar" 42 True

명명 된 필드없이 레코드가 생성되면 컴파일러에서 경고를 내고 결과 값은 undefined .

> let r = RecordType {aString = "Foobar", aNumber= 42}
  <interactive>:1:9: Warning:
     Fields of RecordType not initialized: isTrue
> isTrue r
  Error 'undefined'

값을 설정하여 레코드 필드를 업데이트 할 수 있습니다. 언급되지 않은 입력란은 변경되지 않습니다.

> let r = RecordType {aString = "Foobar", aNumber= 42, isTrue = True}
> let r' = r{aNumber=117}
    -- r'{aString = "Foobar", aNumber= 117, isTrue = True}

복잡한 레코드 유형의 렌즈 를 만드는 것이 종종 유용합니다.

필드 값을 변경하면서 레코드 복사

이 유형이 있다고 가정합니다.

data Person = Person { name :: String, age:: Int } deriving (Show, Eq)

및 두 값 :

alex = Person { name = "Alex", age = 21 }
jenny = Person { name = "Jenny", age = 36 }

alex 에서 복사하여 변경할 값을 지정하여 Person 유형의 새 값을 작성할 수 있습니다.

anotherAlex = alex { age = 31 }

alexanotherAlex 의 값은 다음과 anotherAlex .

Person {name = "Alex", age = 21}

Person {name = "Alex", age = 31}

newtype을 사용한 레코드

레코드 구문은 정확히 하나의 필드가있는 정확히 한 생성자가 있다는 제한하에 newtype 과 함께 사용할 수 있습니다. 여기서 새로운 이점은 newtype을 언랩하는 함수를 자동으로 생성하는 것입니다. 이 필드의 이름은 종종 monads의 경우 run 시작하고 monoid의 경우 get , 다른 유형의 경우 un 로 지정됩니다.

newtype State s a = State { runState :: s -> (s, a) }

newtype Product a = Product { getProduct :: a }

newtype Fancy = Fancy { unfancy :: String } 
  -- a fancy string that wants to avoid concatenation with ordinary strings

레코드 구문은 일반적으로 값을 형성하는 데 사용되지 않으며 필드 이름은 언 래핑에 엄격하게 사용된다는 점에 유의해야합니다

getProduct $ mconcat [Product 7, Product 9, Product 12]
-- > 756

RecordWildCards

{-# LANGUAGE RecordWildCards #-}

data Client = Client { firstName     :: String
                     , lastName      :: String
                     , clientID      :: String 
                     } deriving (Show)

printClientName :: Client -> IO ()
printClientName Client{..} = do
    putStrLn firstName
    putStrLn lastName
    putStrLn clientID

Client{..} 패턴은 생성자 Client 의 모든 필드를 가져오고 패턴과 동일합니다

Client{ firstName = firstName, lastName = lastName, clientID = clientID }

또한 다음과 같은 다른 필드 matcher와 결합 될 수 있습니다.

Client { firstName = "Joe", .. }

이것은

Client{ firstName = "Joe", lastName = lastName, clientID = clientID }

필드 레이블을 사용하여 데이터 유형 정의

필드 레이블을 사용하여 데이터 유형을 정의 할 수 있습니다.

data Person = Person { age :: Int, name :: String }

이 정의는 데이터 형식의 일부에 액세스하는 데 사용할 수있는 레코드 접근 자도 정의하므로 일반 레코드 정의와 다릅니다.

이 예제에서는 agename 필드에 각각 액세스 할 수 있도록 agename 두 개의 레코드 접근자가 정의되어 있습니다.

age :: Person -> Int
name :: Person -> String

레코드 접근자는 컴파일러에 의해 자동 생성되는 하스켈 함수 일뿐입니다. 따라서, 그들은 일반 하스켈 함수처럼 사용됩니다.

필드의 이름을 지정하면 코드를보다 쉽게 ​​읽을 수 있도록 필드 레이블을 여러 다른 컨텍스트에서 사용할 수 있습니다.

패턴 매칭

lowerCaseName :: Person -> String
lowerCaseName (Person { name = x }) = map toLower x

패턴 일치가 정의의 RHS에서 사용될 수있는 새로운 값 (이 경우 x )과 일치하는 동안 관련 필드 레이블의 위치에있는 값을 바인딩 할 수 있습니다.

NamedFieldPunsNamedFieldPuns 패턴 매칭

lowerCaseName :: Person -> String
lowerCaseName (Person { name }) = map toLower name

NamedFieldPuns 확장은 대신 우리가 일치시키고 자하는 필드 레이블을 지정할 수있게 해줍니다.이 이름은 정의의 RHS에서 그림자가 생기므로 name 은 레코드 접근자가 아닌 값을 참조합니다.

RecordWildcardsRecordWildcards 패턴 매칭

lowerCaseName :: Person -> String
lowerCaseName (Person { .. }) = map toLower name

RecordWildCards 사용하여 일치 RecordWildCards 때 모든 필드 레이블이 범위로 가져옵니다. (이 특정 예에서 nameage )

이 확장은 Person 의 정의가 확실하지 않은 경우 값이 범위로 가져 오는 방법이 명확하지 않으므로 약간 논란의 여지가 있습니다.

업데이트 기록

setName :: String -> Person -> Person
setName newName person = person { name = newName }

필드 레이블을 사용하여 데이터 유형을 업데이트하는 특수 구문도 있습니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow