2016-05-09 17 views
2

の使用に起因する(ショー(IO()))なしインスタンス:ちょうど私が私のコンソールWinGHCiにこれをしなかった学習のための '印刷'

let ls = [putChar 'x',putChar 'y'] 

その後、ない場合:

head ls 

私がしなければ、出力はobviusly X(obviusly私はなぜundestand意味で)他の

です:

tail ls 

私はこのエラーを取得する:

No instance for (Show (IO())) arising from a use of ‘print’

In a stmt of an interactive GHCi command: print it

なぜ? yまたは[putChar 'y']を出力しないでください。

+1

'' GHCi'は 'IO'アクションを実行することを知っています - 次のケースで' IO'アクションのリスト( 'Show'のインスタンスではありません)が得られます - ' sequence_ $ tail ls'と似たものを取得する* – Carsten

答えて

11

この現象は、hereと説明されています。

head lsは、タイプIO()です.GCHiはアクションを実行し、結果は()を出力しません。

対照的に、tail lsは、タイプが[IO()]です。

print :: Show a => a -> IO() 

をしかし[IO()]ためのShowインスタンスが存在しないので、あなたがエラーを取得する:これはIOアクションではありませんので、GCHiは型を持つどのprintを使用して、それを表示しようとします。あなたが行動を評価したい場合は、sequence_を使用することができます。

sequence_ (tail ls) 
5

をお持ちの場合は、あなたがそのリストに保存されているアクションを実行していない

> let ls = [putChar 'x', putChar 'y'] 

、あなただけの場合は、それらのアクションを構築していますそれは理にかなっている。あなたは、ファイルに定義されて

printHelp :: IO() 
printHelp = putStrLn "You need to pass XYZ options to this program" 

のようなものを持つことができます。これはただちにメッセージを出力するのではなく、実行されるとそのメッセージをコンソールに出力するアクションを構築します。実行は、main関数とGHCiの2つの場所のいずれかで行われます。

GHCiを使用してコードを実行しているようですが、これはさまざまな機能を調べるのに最適ですが、ファイル内でコードを実行するのとは少し異なります。 GHCiでIO Somethingアクションを単独で評価するたびに、そのIOアクションが実行されます。 GHCiの他の値を評価するたびに、その行の前にprintが挿入されます。あなたは

> head ls 

を行うときにこれはIO()型を持つ、などのアクションputChar 'x'xがコンソールにプリントアウトされ、その結果、実行されます。あなたは

> tail ls 

を行うとGHCiのは、その前に printを入れしようとするので、これは、入力した

> print (tail ls) 

print関数には等価で作り、[IO()]を入力した

print :: (Show a) => a -> IO() 

ここではprintにリストを渡しました。リストの場合はShowのインスタンスがありますが、l istのインスタンスはShowです。したがって、コンパイラはIO()Showのインスタンスがあるかどうかを確認しようとします。残念ながら、IOはかなり複雑なタイプなので、何も起こり得ないことを表しています。コンパイラはIO()Showのインスタンスがないというエラーを表示します。

リスト内のすべてのアクションを順番に実行する場合は、その機能があります:Control.Monad.sequence(または結果を気にしない場合はControl.Monad.sequence_)この関数は実際には、すべてのMonadの上で動作していないだけでIO:うまく

> sequence_ (tail ls) 
y> sequence_ ls 
xy> 
+0

あなたの説明のためにありがとうございます。私は他の正当な理由を選択した最初のものだった。 – granmirupa

6

then if do: head ls the output is obviusly x

actually not obviously!実際にはhead lsは文字'x'に直接関係するものではありません。まずIOのアクションであり、GHCiはこのアクションが何かしたいと思っていると仮定します:IOアクションの場合、アクションを表示しないようにする特別な処置がありますが、を実行します。さて、あなたはそうではなく、ちょうどあなたのビューポートもあることを起こるコンソールに印刷されているアクションが実際に文字'x'につながるんを実行リスト[launchMissiles, putStrLn "oops"] ...

を良く考慮していなかったことあたかもそれがちょうどputChar 'x'の値であるかのように見えます。しかし、そうではありません!

OTOH、tail lsは外部からのものであるため、ghciは何か実行することを想定していません。 を表示しようとするとのリストが表示されますが、のIOアクションまたはその中にIOアクションを持つものを表示できません。それはエラーメッセージの内容です。

0

tail lsだけではなく、lsまたはinit lsを入力すると、同じエラーが発生します。

lsのタイプがある:あなたがGHCiの中に何かを入力すると、それは

ls :: [IO()] 

式を評価し、結果を印刷します。後者の場合(ls)で

lsの種類から、返された値は、アクションのリストで、GHCIO()のアクションを表示する方法を知りません。

最初のケースでは、GHCiはxを出力するIO()を評価します。 IO()にはの戻り値がないため、何も表示されず、エラーもありません。

関連する問題