Haskell Questチュヌトリアル-ホヌル

ほずんどの堎合、これは時間通りに発行される最埌の郚分です。 私の䌑暇はもうすぐ終わり、今では週に蚘事を曞くのは非垞に難しいでしょう。 Haskell Quest Tutorialに興味を持っおいたすべおの人に感謝したす

居間
あなたはリビングルヌムにいたす。 東には出入り口、西には奇劙なゎシック様匏の文字が描かれた朚補のドア、閉ざされおいるように芋える、トロフィヌケヌス、郚屋の䞭倮に倧きな東掋の敷物がありたす。
トロフィヌケヌスの䞊には、叀き良き時代の゚ルフの剣がかかっおいたす。
トロフィヌケヌスには、バッテリヌ駆動の真鍮補ランタンがありたす。


内容
あいさ぀
パヌト1-先
パヌト2-フォレスト
パヌト3-ポリアナ
パヌト4-キャニオンのビュヌ
パヌト5-ホヌル

パヌト5
ここでは、小さな゚ラヌから重芁な結果を導き出し、ゲヌムにオブゞェクトを远加したす。


たず、蚘憶をリフレッシュしたしょう。 4番目のパヌトで取埗したrun関数に぀いお芋おいきたしょう。 ご芧のずおり、私はあなたのために働いお、Lookアクションを远加したした。 実行機胜が印象的になりたした。

curLoc = doを実行したす
putStrLn  describe curLocを蚘述
putStr 「コマンドを入力」
x < -getLine
のケヌス  convertStringToAction x 
終了-> putStrLn 「 䌚い たしょう...」
芋お-> やる
putStrLn  describe curLocを蚘述
curLocを実行したす
Go dir- > do
putStrLn  " \ n You walking to" ++ show dir ++ "。 \ n " 
実行 walk curLoc dir 
convertResult- > do
putStrLn  evalAction convertResult 
putStrLn 「タヌン終了。 \ n "
curLocを実行したす


最埌の2番目のタスクでは、「describeLocation curLoc」ぞの2぀の呌び出しを回避する方法に぀いお考える提案がありたした。 もちろん、1぀の小さな関数の䟋を䜿甚しおリ゜ヌスを奪い合うためにN䜓の重力問題を解決するわけではありたせんが、この重芁性からいく぀かの重芁な結果が生じたす。 呜什型蚀語がある堎合、結果を倉数に割り圓おるだけです。 Haskellでは、デヌタは䞍倉であるず芋なされるため、そのような割り圓おはありたせん。 しかし、刀明したように、割り圓おを䞀般化するだけでなく、倉曎されおいない状態を考慮しお、興味深い効果をもたらす他のメカニズムがありたす。 たずえば、実行の決定論。 実際、グロヌバルな状態が関数に圱響せず、その内郚でデヌタが明らかに倉曎されおいない堎合、同じ匕数に同じ倀を返すこずを意味したす。 関数を1回呌び出すこずで、パラメヌタヌず結果を蚘憶できたす。同じパラメヌタヌで2回呌び出す必芁がある堎合は、前に蚈算した結果を単玔に返したす。

しかし、ビゞネスに取りかかりたしょう。 私たちの問題にはいく぀かの解決策がありたす。 たず、getLineからの行ず倉数xを接続したのず同じ方法で、結果を倉数に関連付けおみたす。 これは割り圓おに䌌おおり、ここでの考え方は簡単です。必芁なだけ倉数を䜿甚できたす。 最初の呌び出しから、おおよそ次のコヌドを取埗したす。

curLoc = doを実行したす
locDescr < -describeLocation curLoc
putStrLn locDescr
putStr 「コマンドを入力」
x < -getLine
のケヌス  convertStringToAction x 
...- 残りのコヌド


しかし、このコヌドはコンパむルされないため、トリックです。

*メむン> r
[ 2 of 2 ] Mainのコンパむル H\ Haskell \ QuestTutorial \ Quest \ QuestMain。Hs 、解釈枈み

H\ Haskell \ QuestTutorial \ Quest \ QuestMain hs 58  17 
予期されたタむプ ' [ a0 ] 'を実際のタむプ ' IO   'ず䞀臎させるこずができたせんでした
' putStrLn 'の呌び出しの戻り 型
「 do 」匏の文  putStrLn locDescr
匏では
...

倱敗したした。モゞュヌルがロヌドされたしたTypes 。


「x <-getLine」ず「locDescr <-describeLocation curLoc」の違いは䜕ですか 同じこずのようですgetLine関数は、倉数xに関連付けられた文字列を返したす。 たた、関数describeLocation curLocは、別のlocDescr倉数にバむンドする文字列も返したす。 しかし、むンタヌプリタヌはいく぀かのタむプが䞀臎しないず蚀いたす。 状況を芋おみたしょう。そしお、このためには、run関数で実際に䜕が起こるかを理解する必芁がありたす。

゚ラヌのある行をコメントアりトしお、䜜業コヌドに戻りたしょう。

curLoc = doを実行したす
-locDescr <-describeLocation curLoc
-putStrLn locDescr
putStr 「コマンドを入力」
x < -getLine
のケヌス  convertStringToAction x 
...- 残りのコヌド

*タむプ> r
[ 2 of 2 ] Mainのコンパむル H\ Haskell \ QuestTutorial \ Quest \ QuestMain。Hs 、解釈枈み
OK 、ロヌドされたモゞュヌルMain 、 Types 。
*メむン>


そのタむプの耇雑さに入らないように、意図的にrun関数の定矩を䜜成したせんでした。 しかし、圌女には型があり、コンパむラヌは自分でそれを忠実に衚瀺したす。 チェック

*メむン> 実行
実行::ロケヌション-> IO  


そしお、ここで驚きが埅っおいたす。 Locationは単䞀のパラメヌタヌの型であり、奇劙な型IOの堎合、戻り倀の型以倖は䜕もありたせん。 ずおも面癜い 結局のずころ、どこでもIOを䜿甚しおいたせん。どこから来たのですか Haskellの暗い行為ず意性のせいですでにHaskellを責めようずしおいる堎合は、急がないでください。 実際には、Haskellによるず、入出力I / Oアクションは朜圚的な゚ラヌおよび障害であり、「副䜜甚」ずしおも知られおいたす。 したがっお、入出力関数putStrLn、putStr、putChar、getLine、getChar、readFile、writeFileは危険であり、同じ匕数に異なる結果を返すこずがあり、堎合によっおぱラヌをスロヌするこずさえありたす。 したがっお、これらはIO型であり、蚀語の芳点では、私たちに関係するはずです。 さらに、内郚にIOタむプを持぀他のすべおの関数も非決定性になり、採甚する必芁がありたす。 run関数は安党でないアクションを遞択したため、IOタむプに感染したした。 ちなみに、プログラムぞの゚ントリポむントメむン関数は、runが呌び出されるため、この運呜を逃れたせんでした。

* Main > t main
メむン:: IO  


公平に蚀えば、説明ではIOアクションを䌎う関数は非決定的であるずいう仮定がなされおいるず蚀う䟡倀がありたす。 実際、これは完党に真実ではありたせん。 ある意味でそのような関数は決定論的であり、玔粋でさえありたす。 この質問は、䞀般的に蚀えば、Haskellの玔床に関する議論の぀たずきのブロックであり、その議論はむンタヌネットで芋぀けるこずができたす。


䞊蚘は私たちの問題にどのように関係しおいたすか 間違ったコヌドをコンパむルせずにもう䞀床芋おみたしょう。実行関数の定矩を順番に割り圓おたす。

実行::ロケヌション-> IO  
curLoc = doを実行したす
locDescr < -describeLocation curLoc
putStrLn locDescr
putStr 「コマンドを入力」
x < -getLine
のケヌス  convertStringToAction x 
...- 残りのコヌド


知っおいるように、doキヌワヌドはアクションをチェヌンにリンクしたすが、チェヌンにはリンクしたせん。 do-notationでは、チェヌン内のすべおのアクションが同じ型を返す必芁がありたす。 I / Oで䜜業するため、関数のタむプにはIOが含たれおいる必芁がありたす。

*メむン> t putStrLn
putStrLn :: 文字列 -> IO  

* Main > t putStr
putStr :: 文字列 -> IO  


String型の匕数に加えお、これらの2぀の関数は同じ戻り倀型-IOを持っおいたす。 ここでの空の括匧は、有甚なものが䜕も返されないこずを瀺したす。 実際、コン゜ヌルに匕数を出力するだけであれば、putStrLnが䜕を返すかは関係ありたせん。 それどころか、getLine関数には「有甚な」䜕かが期埅されたすが、これは独自の方法でそのタむプに反映されたす。

* Main > t getLine
getLine :: IO 文字列


getLineはナヌザヌから文字列を受け取り、それをギフトずしおIOタむプにパックしたす。 そしお、あなたがギフトで䜕でもしたいです。 たずえば、convertStringToAction関数に枡したす。

...
x < -getLine
のケヌス  convertStringToAction x 
...


しかし、convertStringToAction関数には異なる型がありたす -あなたを叫び、あなたは正しいでしょう。 圌女はIO Stringではなく、入力でStringを埅っおいたす トリックは䜕ですか さお、これらの2行のどこかでギフトが展開され、IOボックスは捚おられ、空癜行はすでに進んでいたす。 そしお、これは矢印によっお行われたす。 パックされた結果を右偎から取埗し、巊偎の倉数にアンパックしたす。 ずころで、この操䜜は割り圓おではなくバむンディングず呌ばれたす。 考えおみるず、右偎のどこにも䜕も詰め蟌たれおいないため、「locDescr <-describeLocation curLoc」ずいう衚珟は間違っおいたす。読み取り、結果はIOボックスに入れられたせん。

* Main > t ロケヌションホヌムの説明
 describeLocationホヌム :: 文字列


さお、ここにありたす...できるだけシンプルにしたかったのですが、倚くのペヌゞがどのような結果をもたらしたした。 しかし、私はあなたに朗報がありたす解決策がありたす 私たち自身が右偎にあるものをタむプIOに詰め蟌み、矢印を窒息させたす。 これには戻り関数がありたす。 次のコヌドは意図したずおりに機胜したす。

実行::ロケヌション-> IO  
curLoc = doを実行したす
locDescr < -return  describeLocation curLoc 
putStrLn locDescr
putStr 「コマンドを入力」
x < -getLine
のケヌス  convertStringToAction x 
終了-> putStrLn 「 䌚い たしょう...」
芋お-> やる
putStrLn locDescr
curLocを実行したす
...- 残りのコヌド


はい、戻り関数は文字列をdoIOブロックタむプにパックし、矢印はそれをアンパックしおlocDescr倉数に関連付けたす。 たた、堎所の説明を䜕床も蚈算する必芁がなくなりたした。 もちろん、論理は珍しいですが、あなたは同意する必芁がありたすそれには䜕らかの内面的な矎しさがありたす。 飲む䟡倀あり

IOの衚蚘法ずタむプには、さらに倚くの結果ず萜ずし穎がありたす。 より深く掘り䞋げるず、副䜜甚だけでなく、IOアクションずは異なる法則に埓っお関連付けるこずができる他の倚くの蚈算も、普遍的な方法で調敎できたす。 いわゆるモナドを䜿甚しお蚈算を行うず、驚くほどシンプルで䟿利なロゞックになり、コヌドは簡朔で理解しやすく、衚珟力になりたす。 このようなコヌドは厳密に数孊的で非垞に䟿利であるこずが重芁です。 解析、DSL、可倉状態など、特定のタスクを蚘述するのに非垞に適しおいたす。 おそらくい぀かこのトピックに戻りたすが、これが実際に必芁になるのはそれ以前です。


さお、私たちは問題を解決したした。 では、なぜ他の解決策を考え出す必芁があるのでしょうか はい、䞀般的には、同じこずです。Haskellに぀いお䜕か他のこずを孊ぶこずです。

次の゜リュヌションでは、whereコンストラクトを䜿甚したす。 これは、ここでのみ利甚可胜な関数を蚘述するこずができる特別な構造です-他のプログラミング蚀語の入れ子関数のように。 whereブロック内では、芪関数の倉数が䜿甚可胜であり、通垞の関数に適甚されるすべおの法則が適甚されたす。 ぀たり、同じ関数の耇数のバリアントを䜜成し、パタヌンマッチング、セキュリティ匏を䜿甚し、さらにネストされたwhere-constructionを䜜成できたす。

構造が特別な説明を必芁ずしない堎合、䟋を芋おください

実行::ロケヌション-> IO  
curLoc = doを実行したす
putStrLn locDescr
putStr 「コマンドを入力」
x < -getLine
のケヌス  convertStringToAction x 
終了-> putStrLn 「 䌚い たしょう...」
芋お-> やる
putStrLn locDescr
curLocを実行したす
...- 残りのコヌド
どこで
locDescr = describeLocation curLoc


whereブロックの前にdoブロックず同じむンデントを䜜成したした。 基本的に、このブロックの堎所を定矩したした。 結果を倉数locDescrに割り圓おおいるように芋えるかもしれたせんが、そうではありたせん。 ここには倉数ず割り圓おはありたせん。 locDescrは、堎所の説明を返す関数です。 この関数を芪コヌドから2回呌び出したす。 ただし、ほずんどの堎合、䞀床だけ蚈算されたす。 Haskellコンパむラは、過去の結果を再利甚のために保持できたす。 デヌタが䞍芁になるず、組み蟌みのガベヌゞコレクタヌによっお削陀されたす。 フィボナッチ数が蚈算される最埌の郚分のサむドバヌを思い出しおください。 再垰の各ステップで倀が最初から蚈算された堎合、プログラムはどのように機胜したすか

最埌に、最埌の解決策-いわゆるlet匏-が最も単玔で、おそらくここで最も適切です。 たた、let匏はwhereず非垞に䌌おいたすが、匏の゚むリアスを定矩したすが、そのような名前の関数は定矩したせん。 doブロック内では、let匏は次のようになりたす。

実行::ロケヌション-> IO  
curLoc = doを実行したす
let locDescr = describeLocation curLoc
putStrLn locDescr
putStr 「コマンドを入力」
x < -getLine
のケヌス  convertStringToAction x 
終了-> putStrLn 「 䌚い たしょう...」
芋お-> やる
putStrLn locDescr
curLocを実行したす
...- 残りのコヌド


doブロックの倖偎、たずえば他の匏の内偎でlet匏を䜿甚するず、レコヌドはわずかに倉わりたす。 inキヌワヌドが远加されたす。

実行::ロケヌション-> IO  
curLoc =を実行したす
let locDescr = describeLocation curLoc in
する
putStrLn locDescr
putStr 「コマンドを入力」
x < -getLine
のケヌス  convertStringToAction x 
終了-> putStrLn 「 䌚い たしょう...」
芋お-> やる
putStrLn locDescr
curLocを実行したす
...- 残りのコヌド


実際、letずinの間にこのような匏をいく぀でも定矩できたす。オブゞェクトの远加に進むず、これがどのように行われるかがわかりたす。 それたでは、let匏がdoブロック内にある前のオプションをそのたたにしたす。

Let匏は短く曞かれおいるだけでなく、いく぀かの特別な堎合に䜿甚できるため、優れおいたす。 そのため、たずえば、同じ目的でリスト内包衚蚘にletを挿入できたす。スコヌプを制限しお匏を定矩したす。 ただし、欠点もある堎所ず比范しお、ガヌド匏ずパタヌンマッチングを䜿甚するこずはできたせん。 もちろん、私たちは仮名を定矩しおいるので、その範囲内でそれらを繰り返すべきではありたせん。


オブゞェクトに到達したずきに尋ねたすか 私はすでに切り替えおいたす。 あなたはただですか その埌、远い぀く。 次のように、オブゞェクトのADTタむプを䜜成したす。

デヌタオブゞェクト=テヌブル
| 傘
| 匕き出し
| 電話番号
| メヌルボックス
| フレンドキヌ
導出  Eq 、 Show 、 Read 


堎所の画像に、オブゞェクトの説明を含む関数を远加したす。

describeObject :: Object- > String
describeObject Umbrella = "玠敵な赀いメカニックの傘。"
describeObject Table = "匕き出し付きの良い朚補テヌブル。"
describeObject Phone = "電話には音声メッセヌゞがありたす。"
describeObject MailBox = "メヌルボックスが閉じおいたす。"
describeObject obj = "特別なこずは䜕もありたせん" ++ show obj


トリックはありたせん、私たちはすでにこれをすべお知っおおり、私たちはできるのです。 新しいオブゞェクトは、堎所のオブゞェクトを定矩する必芁があるずきに始たりたす。 もちろん、すべおの準備が敎い、テむクアンドドロップアクションが機胜し、むンベントリ、耇合オブゞェクトがあったこずを望みたす...しかし、これは起こりたせん。 次に、オブゞェクトのドラフトバヌゞョンを䜜成たたはスロヌできない堎所で䜜成し、それに基づいお他のより高床で適切なメカニズムを考えたす。

ゲヌムが始たるホヌムの堎所にいく぀かのオブゞェクトがあり、その䞭にテヌブル、テヌブル匕き出し、電話、傘があるず仮定したす。 この堎所のオブゞェクトのリストを返すlocationObjects関数を蚭定したす。

locationObjects ::堎所-> [オブゞェクト]
locationObjectsホヌム= [傘、匕き出し、電話、テヌブル]
locationObjects _ = [ ]


䞀般的に、リストはシンプルに芋えたす。 オブゞェクトのリストは[オブゞェクト]の䞀皮です。 ホヌムの堎所に぀いおは、4぀のオブゞェクトのリストを返したす。 空のリストは、他のすべおの堎所にオブゞェクトがない限り、空の角括匧で瀺されたす。 先に進む前にコヌドをテストする䟡倀がありたす。

*メむン> locationObjectsホヌム
[傘、匕き出し、 Phome 、テヌブル]

* Main > locationObjects Garden
[ ]

*メむン> describeObjectテヌブル
「匕き出し付きの良い朚補テヌブル。」


Object型はShow型クラスから継承されるため、show関数は型コンストラクタヌだけでなく、この型のリストにも䜿甚できたす。

*メむン>傘を衚瀺
傘

*メむン> ショヌ [傘、テヌブル]
「[傘、テヌブル]」

* Main > show  locationObjects Home 
「[傘、匕き出し、電話、テヌブル]」

* Main > putStrLn  show  locationObjects Home  
[傘、匕き出し、電話、テヌブル]


逆もたた真です。 読み取り関数でリスト項目を解析できる堎合、リスト党䜓も解析できたす。

* Main > read "[Table、MailBox]" :: [ Object ]
[衚、メヌルボックス]


構文が理解できたので、珟圚の堎所に぀いお説明が衚瀺されるだけでなく、そこにあるオブゞェクトのリストも印刷されるように構文を䜜成したす。 let匏を䜿甚しおみたしょう。

curLoc = doを実行したす
let locDescr = describeLocation curLoc
let objectsDescr = " \ nここにはいく぀かのオブゞェクトがありたす" ++ show  locationObjects curLoc 
let fullDescr = locDescr ++ objectsDescr
putStrLn fullDescr
...- 残りのコヌドは、Lookアクションを曎新するこずを忘れないでください。


プログラムの出力は次のようになりたす。

*メむン>メむン
Haskellでのク゚ストアドベンチャヌ。

ホヌム
あなたは朚補のテヌブルの真ん䞭の郚屋に立っおいたす。
ここにはいく぀かのオブゞェクトがありたす [傘、匕き出し、電話、テヌブル]
コマンドを入力しおください


コヌドには少し面倒です。 その堎所にオブゞェクトがなくおも、「ここにはオブゞェクトがいく぀かありたす」ずいう碑文は、ただ目障りです。

コマンドを入力Go North

北ぞ歩いおいたす。

庭
あなたは庭にいたす。 .....
ここにはいく぀かのオブゞェクトがありたす [ ]
コマンドを入力しおください


オブゞェクトの空のリストに察しお衚瀺しないように、オブゞェクトを蚘述するためのすべおのコヌドを別の関数に入れ、enumerateObjectsず呌びたす。 入力ではリストを受け取り、出力ではリストされたオブゞェクトを含む文字列を枡したす。

enumerateObjects :: [オブゞェクト] -> 文字列
enumerateObjects [ ] = ""
enumerateObjects objects = " \ nここにはいく぀かのオブゞェクトがありたす" ++オブゞェクトを衚瀺


enumerateObjects関数の最初のバリアントは空の文字列を返したすが、転送されたオブゞェクトのリストが空の堎合のみです。 空でない堎合、最初のオプションは拒吊され、2番目のオプションが機胜したす。 実行機胜

curLoc = doを実行したす
let locDescr = describeLocation curLoc
let objectsDescr = enumerateObjects  locationObjects curLoc 
let fullDescr = locDescr ++ objectsDescr
putStrLn fullDescr
... -...


たたは、必芁に応じお、doブロックからlet匏を匕き出すこずができたす。

curLoc =を実行したす
させる
locDescr = describeLocation curLoc
objectsDescr = enumerateObjects  locationObjects curLoc 
fullDescr = locDescr ++ objectsDescr
やる
putStrLn fullDescr
... -...


この単玔なリファクタリングのおかげで、実行に圱響を䞎えずにenumerateObjects関数を倉曎できるようになりたした。 したがっお、オブゞェクトを列挙するだけでなく、オブゞェクトの説明も衚瀺したいので、遊び心のあるペンでenumerateObjectsにアクセスしお、そこにある䜕かを修正したした。 しかし、どういうわけか埌で。 次に、カスタムアクションInvestigateを远加したしょう。 このコマンドにより、プログラムはオブゞェクトの詳现な説明を提䟛する必芁がありたす。 ナヌザヌが次のように入力する必芁があるこずは明らかです。

コマンドを入力傘の調査


「Investigate Umbrella」ずいう行を解析する必芁がありたす。 おなじみですか 既にGoチヌムでこれを行っおいたす。 ここでも同じです。InvestigateコンストラクタヌにObjectパラメヌタヌを配眮するだけです。

デヌタアクション=
...
| オブゞェクトを調査する
...


ほんの少しだけ-実行機胜を修正するには

curLoc = doを実行したす
...
...
のケヌス  convertStringToAction x 
objを調査する-> do
putStrLn  describeObject obj 
curLocを実行したす
...


そしお出来䞊がり 別のナヌザヌアクションを実装したした おめでずうございたす コマンド「Investigate Umbrella」を入力するず、プログラムに「Nice red mechanic Umbrella」ずいう文字列が衚瀺されるこずを確認できたす。

それだけです...私たちの悪いずころを知っおいたすか ホヌムの堎所で「Investigate MailBox」コマンドを入力するず、メヌルボックスの説明が衚瀺されたすが、ここからはたったく芋えたせん それでは、オブゞェクトが芋぀かった堎合にTrueを返すisVisible関数を考えたす。この堎合のみ、オブゞェクトの説明を発行したす。 isVisible関数の匕数は䜕ですか 調査察象のオブゞェクトず、すべおのロケヌションオブゞェクトのリストが必芁です。 このようなもの

isVisible ::オブゞェクト-> [オブゞェクト] -> Bool


このリストにオブゞェクトがあるかどうかをどうにかしお調べる必芁がありたす。 リスト内のすべおのオブゞェクトを列挙する「愚かな」オプションは考えられたせんが、これは非垞に可胜ですが、暙準のelem関数を䜿甚するだけです。 芁玠ずリストの2぀のパラメヌタヌを取りたす。 リスト内にアむテムが芋぀かった堎合、Trueを返したす。 必芁なもの

isVisible ::オブゞェクト-> [オブゞェクト] -> Bool
isVisible objオブゞェクト= elem objオブゞェクト


Haskellには特別な衚蚘法があり、関数を匕数の間に配眮したす-意味の明確さず透明性を高めたす。 これを行うには、関数を逆アポストロフィ、ボタン䞊にあるもので囲む必芁がありたす。

isVisible ' ::オブゞェクト-> [オブゞェクト] -> Bool
isVisible 'obj objects = obj ` elem`オブゞェクト


しかし、同じ機胜の「ダム」バヌゞョン。 それらの䞭で、リスト内のオブゞェクトを手動で探したす。

isVisible '' ::オブゞェクト-> [オブゞェクト] -> Bool
isVisible '' obj [ ] = False
isVisible '' obj  oos  =  obj == o  ||  isVisible '' obj os 

isVisible '' ' ::オブゞェクト-> [オブゞェクト] -> Bool
isVisible '' 'obj [ ] = False
isVisible '' 'objオブゞェクト=  obj == ヘッドオブゞェクト ||  isVisible '' 'obj  テヌルオブゞェクト 


それらは同じように機胜し、違いは䜿甚する手段のみです。 そこずそこの䞡方で、リストは郚分に分割されたす残りの芁玠のヘッド芁玠ずテヌル。 最初の䟋では、リストぱントリoosを䜿甚しお分割されたす。 倉数「o」にはヘッドが含たれ、倉数「os」には他のすべおが含たれおいるこずは明らかです。 2番目の䟋では、ヘッドリストずテヌルリストの䞊の組み蟌み関数でのみ同じこずを行いたす。 次に、オブゞェクトがhead芁玠ず䞀臎するかどうかを確認し、䞀臎しない堎合は、残りの芁玠に察しおisVisibleを再垰的に呌び出したす。 再垰が無限にならないようにするために、関数「isVisible obj [] = False」のバリアントを远加したした。リストのすべおの芁玠を突然噛んで、䜕も残っおいない堎合に機胜したす。


さお、残っおいるのはこの機胜を䜿甚するこずだけです。 い぀ものように、runを倉曎し、珟圚の堎所のオブゞェクトを数回芁求しないように、それらをlet匏に入れたす。

curLoc = doを実行したす
let locObjects = locationObjects curLoc
let locDescr = describeLocation curLoc
let objectsDescr = enumerateObjects locObjects
let fullDescr = locDescr ++ objectsDescr
putStrLn fullDescr
putStr 「コマンドを入力」
x < -getLine
のケヌス  convertStringToAction x 
objを調査する-> do
if  isVisible obj locObjects 
次に putStrLn  describeObject obj 
else putStrLn  "衚瀺されたせん" ++ show obj ++ "here。" 
curLocを実行したす
終了-> putStrLn 「 䌚い たしょう...」
...- 残りのコヌド


以䞊です。 この重芁な泚意事項を停止したす。䌑憩の時間です。すでに膚倧な知識がありたす。

修正のための割り圓お。

1.オブゞェクトに関連するすべおの機胜をオブゞェクトモゞュヌルに、堎所に関連するすべおの機胜を堎所モゞュヌルに転送したす。
2.ロケヌションオブゞェクトの実隓的結論を次の圢匏で䜜成したす。

 ホヌム
あなたは朚補のテヌブルの真ん䞭の郚屋に立っおいたす。
  ここにはいく぀かのオブゞェクトがありたす。
     傘玠敵な赀い敎備士の傘。
     テヌブル匕き出し付きの良い朚補テヌブル。
     電話電話には音声メッセヌゞがありたす。
     匕き出し匕き出しには特別なものはありたせん。 


3. Investigateアクションの凊理をリファクタリングするには、このための個別の関数を䜜成したす。 リファクタリング埌のrun関数のコヌドは次のようになりたす。

...
objを調査する-> do
putStrLn  obj locObjectsを調査
curLocを実行したす
...


この郚分の゜ヌス 。

目次、参照、および远加情報はGreetingsにありたす。

Source: https://habr.com/ru/post/J123422/


All Articles