プログラミング Haskell 第 2 版

プログラミング Haskell 第 2 版

 プログラミングHaskell 第2版
Grahum Hutton
ラムダノート
2019-08-02
¥ 3,456

第6章 再帰関数

6.5 相互再帰

p.67

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

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

p.067.hs

  1
  2
  3
  4
  5
  6
  7
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文

<エラー調査>

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

  • Preludeの関数をhidingで隠す - 結城浩のHaskell日記 - haskell

    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 プログラミング入門

    ●モジュールの使い方
    Haskell の場合、モジュールは import 文を使って読み込みます。

    import モジュール名

    必要な関数 (変数) だけインポートすることもできます。

    import モジュール名 (名前, ...)

    モジュール名の後ろのカッコの中にインポートする関数を指定します。逆に、インポートしたくない関数を指定することもできます。

    import モジュール名 hiding (名前, ...)

    hiding を付けると、指定された関数はインポートされません。それ以外の関数はすべてインポートされます。

実験のため、Preludeモジュールの標準関数を隠す必要がある場合、

import Xxx hiding (yyy)

のように、先頭でインポートしない宣言をしておく必要がある。
odd, evenは標準関数なので、名前が重複していた?

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



p.67(続き)

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


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2019-08-28 (水) 00:36:16 (80d)