質問
私は機能的なプログラミングとHaskellに非常に慣れていないので、私に耐えてください。 Haskellに関数を書き込もうとしています。Haskellは、整数のリストを取得し、上記のリストのヘッドを印刷してからリストの尾を返します。関数は[整数] - > [整数]タイプである必要があります。少しのコンテキストを与えるために、私は通訳を書いています。この関数は、それぞれのコマンドが連想リストで調べられたときに呼び出されます(キーはコマンド、値は関数です)。
これが私が書いたコードです:
dot (x:xs) = do print x
return xs
コンパイラは次のエラーメッセージを提供します。
forth.hs:12:1:
Couldn't match expected type `[a]' against inferred type `IO [a]'
Expected type: ([Char], [a] -> [a])
Inferred type: ([Char], [a] -> IO [a])
In the expression: (".", dot)
ドット関数で印刷する呼び出しは、推定されたタイプをIO [a]にする原因であると思われます。返品する必要があるのは、リストの尾がドットに渡されるだけなので、リターンのプリントの種類を無視できる方法はありますか。
前もって感謝します。
解決
ほとんどの機能的な言語では、これは機能します。ただし、Haskellはaです ピュア 機能的言語。関数でIOを行うことは許可されていないため、関数は
[Int] -> [Int]
IOまたは[Int] -> IO [Int]
IOで
タイプの dot
コンパイラによって推測されるように dot :: (Show t) => [t] -> IO [t]
しかし、あなたはそれを宣言することができます [Int] -> IO [Int]
:
dot :: [Int] -> IO [Int]
IO Monadを参照してください: http://book.realworldhaskell.org/read/io.html
私は言及していません System.IO.Unsafe.unsafePerformIO
それは細心の注意を払って、その結果をしっかりと理解して使用する必要があります。
他のヒント
いいえ、機能は副作用(別名IO、この場合は画面に印刷)を引き起こします。 print
IOは、何かを返します IO
そして、これは元に戻すことはできません。
そして、コンパイラがだまされて忘れてしまうなら、それは悪いことでしょう IO
. 。たとえば、あなたの場合 [Integer] -> [Integer]
機能は、同じパラメーターを使用してプログラムで何度か呼ばれます( []
たとえば、コンパイラは、関数を1回だけ実行するだけで、その結果を「呼び出された」すべての場所でその結果を使用する場合があります。あなたの「隠された」プリントは、いくつかの場所で関数を呼び出したにもかかわらず、一度しか実行されません。
しかし、タイプシステムはあなたを保護し、使用するすべての機能を確認します IO
, 、間接的にのみであっても、 IO
これを反映するタイプ。純粋な関数が必要な場合は、使用できません print
初期化。
すでにご存知かもしれませんが、Haskellは「純粋な」機能的プログラミング言語です。このため、副作用(画面に値を印刷するなど)は、より主流の言語であるため、偶発的ではありません。この事実は、Haskellに多くの素晴らしいプロパティを与えますが、あなたがしているのは画面に値を印刷しようとするだけで、これを気にしないことを許されるでしょう。
言語には副作用を引き起こすための直接的な機能がないため、戦略は、関数が1つ以上の「IOアクション」値を生成する可能性があることです。 IOアクションは、値を生成するとともに、いくつかの副作用(コンソールへの印刷、ファイルへの書き込みなど)をカプセル化します。あなたの dot
関数はまさにそのようなアクションを生成しています。あなたが今持っている問題は、IOの副作用を引き起こすことができるものと、値を解き放ち、おそらくそれをあなたのプログラムに渡すことができるということです。
ハッキングに頼らずに、これはIOアクションをバックアップする必要があることを意味します main
働き。実際に言えば、これは間のすべてを意味します main
と dot
「Io Monad」にいる必要があります。 「Io Monad」で何が起こるかは、いわば「Io Monad」にとどまります。
編集
これが私があなたを使うために想像できる最も単純な例についてです dot
有効なHaskellプログラムの機能:
module Main where
main :: IO ()
main =
do
let xs = [2,3,4]
xr <- dot xs
xrr <- dot xr
return ()
dot (x:xs) =
do
print x
return xs