#author("2019-08-27T17:24:23+00:00","default:sagasite","sagasite")
[[プログラミング Haskell 第 2 版 >Programming-in-Haskell-2nd-edition]]

*プログラミング Haskell 第 2 版 [#kb7c4c14]

#html{{
<table border="0" cellpadding="5"><tr><td valign="top"><a href="https://www.amazon.co.jp/exec/obidos/ASIN/4908686076/vertex9-22/" target="_blank"><img src="https://images-fe.ssl-images-amazon.com/images/I/41Korrd80qL._SL160_.jpg" border="0"></a></td><td> </td><td valign="top"><a href="https://www.amazon.co.jp/exec/obidos/ASIN/4908686076/vertex9-22/" target="_blank">プログラミングHaskell 第2版</a><br>Grahum Hutton<br>ラムダノート<br>2019-08-02<br>¥ 3,456</td></tr></table>
}}

*第6章 再帰関数 [#z8bb2e5d]

**6.5 相互再帰 [#eaa0312f]

p.67

>関数は相互再帰を使っても定義できます。
相互再帰とは、二つ以上の関数がお互いを参照し合うことです。

>たとえば、プレリュード関数 evenと oddを考えてみましょう。

p.067.hs
#code(haskell){{
even :: Int -> Bool
even 0 = True
even n = odd (n-1)

odd :: Int -> Bool
odd 0 = False
odd n = even (n-1)
}}

これをWinGHCiにロードするとエラーが発生した。

 Failed, no modules loaded.
 Prelude> 
 p067.hs:6:10: error:
     Ambiguous occurrence ‘odd’
     It could refer to either ‘Prelude.odd’,
                              imported from ‘Prelude’ at p067.hs:1:1
                              (and originally defined in ‘GHC.Real’)
                           or ‘Main.odd’, defined at p067.hs:9:1
   |
 6 | even n = odd (n-1)   |          ^^^
 
 p067.hs:10:9: error:
     Ambiguous occurrence ‘even’
     It could refer to either ‘Prelude.even’,
                              imported from ‘Prelude’ at p067.hs:1:1
                              (and originally defined in ‘GHC.Real’)
                           or ‘Main.even’, defined at p067.hs:5:1
    |
 10 | odd n = even (n-1)    |         ^^^^

***Haskellモジュールのimport文 [#xe40b16c]

<エラー調査>

「Ambiguous occurrence」 → 直訳「あいまいな発生」

-[[haskell Ambiguous occurrence error - Google 検索>https://www.google.com/search?q=haskell+Ambiguous+occurrence+error&lr=lang_ja]]

-[[Preludeの関数をhidingで隠す - 結城浩のHaskell日記 - haskell>https://haskell.g.hatena.ne.jp/hyuki/20060620/hiding]]
>Preludeモジュールを明示的にimportしておき、hiding構文を使うとインポートを防止することができます。
たとえば以下のようにmapを定義しようとするとエラーになります。
 map _ [] = []
 map f (x:xs) = f x : map f xs
GHCiでの実行結果です。
 Compiling Main             ( a.hs, interpreted )
 a.hs:2:21:
     Ambiguous occurrence `map'
     It could refer to either `Main.map', defined at a.hs:1:0
                           or `GHC.Base.map', imported from Prelude at Implicit import declaration
 Failed, modules loaded: none.
以下のようにPreludeモジュールを明示的にimportし、hiding構文でmapを隠します。
 import Prelude hiding (map)
 map _ [] = []
 map f (x:xs) = f x : map f xs
すると、以下のようにエラーがなくなります。

-[[関数 - ウォークスルー Haskell>http://walk.northcol.org/haskell/functions/]]
>import Prelude hiding (even, odd)  -- 標準関数の even, odd を隠すおまじない

まさにこの一行を先頭に入れたら、エラーメッセージが出なくなった。

-[[お気楽 Haskell プログラミング入門>http://www.nct9.ne.jp/m_hiroi/func/haskell08.html]]
>●モジュールの使い方
Haskell の場合、モジュールは import 文を使って読み込みます。
 import モジュール名
必要な関数 (変数) だけインポートすることもできます。
 import モジュール名 (名前, ...)
モジュール名の後ろのカッコの中にインポートする関数を指定します。逆に、インポートしたくない関数を指定することもできます。
 import モジュール名 hiding (名前, ...)
hiding を付けると、指定された関数はインポートされません。それ以外の関数はすべてインポートされます。

実験のため、Preludeモジュールの標準関数を隠す必要がある場合、
 import Xxx hiding (yyy)
のように、先頭でインポートしない宣言をしておく必要がある。
odd, evenは標準関数なので、名前が重複していた?

とりあえず、エラーメッセージが出なくなったので、以後同様の現象が起きたら、このような方法で対処してみよう。

~
p.67(続き)

>Haskell では文字列が文字のリストであることを思い出しましょう。
たとえば、"abcde"は単に ['a','b','c','d','e']の略記法です。

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS