2017-11-25 16 views
0

저는 하스켈에 매우 익숙하고 연습하기 위해 주사위 굴림에 기초한 d & d 스타일 게임을 만들기로 결정했습니다. 그리고 더 큰 숫자의 승리를 얻은 사람이면 누구나 할 수 있습니다. 그러나 나는 내 레코드의 가치를 어떻게 바꾸고 레코드의 글로벌 가치를 바꾸는 지에 대해 다소 혼란 스럽다. 나는을 위해 인터넷을 통해 모두를 검토 한하스켈에있는 레코드의 값 변경하기

takeDamage:: State PlayerStats() 
takeDamage = do 
     let h = defaultStats health 
     h <- get 
     put $ (h - 10) 

: 플레이어가 주사위 롤을 잃으면 내 함수가 피해를하기 위해 여기에

data PlayerStats = PlayerStats { health :: Health 
           ,mana :: Mana 
           ,inventory :: [Items] }deriving (Show,Eq) 




defaultStats = PlayerStats {health = 100, mana = 50, inventory = []} 

그리고 다음은

내 기록 코드 내 문제와 같은 문제에 대한 해결책을 찾지 못했지만 아무 것도 찾지 못했습니다. 그래서 제 상황의 다른 사람들에게 유용 할 수 있다고 생각합니다. 그래서, 기록이 아닌 기능입니다

+0

당신이 말하는'State' 트랜스포머 라이브러리 나 다른 모듈의'Control.Monad.Trans.State'에서 온 것입니까? –

+0

Control.Monad.State를 사용하고 있습니다. – DRutherford

답변

3

첫째, defaultStats :: PlayerStats :

defaultStats health 

이 이해가되지 않습니다. 한편, health :: PlayerStats -> Health는 함수이고, 그래서이 defaultStatshealth 때문에

health defaultStats 

는 더 의미하지만, 본질적으로 일정 100이다. 그러나이 경우 을 즉시 도입하여 get이라는 문자열 (StateControl.Monad.Trans.State이라고 가정)이 현재 PlayerStatsStateMonad에서 가져 오기 때문에이 경우에는 의미가 없습니다. h은 구성 요소가 아닌 전체 PlayerStats이됩니다.

레코드 업데이트는 실제로 하나 이상의 필드가 새로운 값으로 대체 된 기존 레코드에서 레코드를 새로 만듭니다. 이 경우 10 마이너스 현재 값으로 health 필드를 대체 할 : 여기

takeDamage = do 
    ps <- get 
    put $ ps { health = health ps - 10 } 

, 우리는 새로운 PlayerStats 현재의 기준으로 현재 psStateMonad에서 PlayerStats 다음 put를 얻을 수 health 필드는 현재 health에서 10을 뺀 값으로 설정됩니다. 레코드 업데이트 구문에서 = 왼쪽의 health은 필드 이름을 나타내고 오른쪽의 health은 기존 레코드에서 health 필드를 가져 오는 접근 자 기능을 나타냅니다. put 하였다

get는 상태를 변환하는 기능을 취하는 modify 기능이 있다는 충분히 공통이며 getput 함께 랩

takeDamage = modify $ \ps -> ps { health = health ps - 10 } 

기록 업데이트 신택스 거대한 하스켈 사마귀이며 . lenses을 확인하면 StateMonad의 필드를 업데이트하는 것이 매우 쉽습니다 (엉망으로 만들 때 발생하는 오류 메시지가 뇌를 녹이게합니다).당신이 당신의 플레이어가 모든 건강을 잃으면보고 싶다면

편집

, 당신은 플레이어가 살아 있다면 takeDamage 함수는 Bool 표시를 반환 할 수 있습니다 :

takeDamage :: State PlayerStats Bool 
takeDamage = do 
    ps <- get 
    let health' = health ps - 10 
    put $ ps { health = health' } -- update health even if dead! 
    return (health' > 0) 

playRound :: State PlayerStats() 
playRound = do 
    survived <- takeDamage 
    if survived 
    then do 
     ... 
    else do 
     ... 
+0

아, 알겠습니다. 필자가 진지하게 C#, Python 및 JavaScript로 코딩 한 이후로 레코드 구문은 나에게 정말 혼란 스러웠습니다. 그렇다면 나중에 (플레이어가 죽었는지 확인하기 위해) 값을 평가하고 싶다면 if, then, else 컨텍스트에서 구문이 어떻게 보이겠습니까? – DRutherford