71762


ある数がその要素に含まれているかどうかを判定する関数mを作成したいのですが、実行は出来るものの、実行したときに計算してくれません。

どこが間違っていますでしょうか。回答よろしくお願いします。

* * *

**作成したプログラム:**

[code]

    m([],x)=False
    m(as,x)=if memberOf(as,x) then True else False
    memberOf(x,[])=False
    memberOf(x,a:as)=if x==a then True else memberOf(x,as)
    
[/code]

**期待している実行結果:**

[code]

    *Main> m([100,54,89,27,76,45], 76)
    True
    *Main> m([100,54,89,27,76,45], 88)
    False
    
[/code]

**実際の実行結果:**

[code]

    <interactive>:13:1: error:
        • Ambiguous type variable ‘t0’ arising from a use of ‘m’
          prevents the constraint ‘(Eq t0)’ from being solved.
          Probable fix: use a type annotation to specify what ‘t0’ should be.
          These potential instances exist:
            instance Eq Ordering -- Defined in ‘GHC.Classes’
            instance Eq Integer
              -- Defined in ‘integer-gmp-1.0.0.1:GHC.Integer.Type’
            instance Eq a => Eq (Maybe a) -- Defined in ‘GHC.Base’
            ...plus 22 others
            ...plus 8 instances involving out-of-scope types
            (use -fprint-potential-instances to see them all)
        • In the expression: m ([1, 2, 3, 4, ....], 1)
          In an equation for ‘it’: it = m ([1, 2, 3, ....], 1)
    
    <interactive>:13:4: error:
        • Ambiguous type variable ‘t0’ arising from the literal ‘1’
          prevents the constraint ‘(Num t0)’ from being solved.
          Probable fix: use a type annotation to specify what ‘t0’ should be.
          These potential instances exist:
            instance Num Integer -- Defined in ‘GHC.Num’
            instance Num Double -- Defined in ‘GHC.Float’
            instance Num Float -- Defined in ‘GHC.Float’
            ...plus two others
            (use -fprint-potential-instances to see them all)
        • In the expression: 1
          In the expression: [1, 2, 3, 4, ....]
          In the first argument of ‘m’, namely ‘([1, 2, 3, 4, ....], 1)’
    
    <interactive>:13:15: error:
        • No instance for (Num [[t0]]) arising from the literal ‘1’
        • In the expression: 1
          In the first argument of ‘m’, namely ‘([1, 2, 3, 4, ....], 1)’
          In the expression: m ([1, 2, 3, 4, ....], 1)
    
[/code]


CC BY-SA 4.0
2020-11-06T02:47:54.720
71760
2020-11-06T03:36:22.510
2020-11-06T03:16:29.140
3060
41837
question
haskell
Haskellで型エラー: No instance for (Num [[t0]]) arising from the literal ‘1’


※もう自力解決したとのことですが、いいところまで書いてしまったので参考までに。

>
[code]

>     m(as,x)=if memberOf(as,x) then True else False
>  
[/code]

この行で、 `memberOf`関数に渡す引数の順番（正確には、引数に渡すタプルの要素の順番）が入れ替わってしまっているのが原因のようです。

下記のように直すと意図通り動きました:

[code]

    m([],x)=False
    m(as,x)=if memberOf(x,as) then True else False
    memberOf(x,[])=False
    memberOf(x,a:as)=if x==a then True else memberOf(x,as)
    
[/code]

ただ、もう少しこのコードをよくするためにさらにいくつか指摘させてください。

# `memberOf`関数について

`memberOf`関数が`m`関数のやりたいことをすべて満たしてしまっているようなので、実際には下記のように書き換えられるでしょう:

[code]

    m([],x)=False
    m(a:as,x)=if x==a then True else m(as,x)
    
[/code]

# 余分な`if`について

これは好みの問題もありそうですが、一般に`if`の中で`Bool`型の値を返すのは冗長です。  
今回の場合`||`で次のように書き換えるのもよいでしょう:

[code]

    m([],x)=False
    m(a:as,x)=x==a || m(as,x)
    
[/code]

# 関数の呼び出し・定義の構文について

恐らく`func(x,
y)`という構文を、ほかのプログラミング言語に引きずられて、複数の引数を渡すときの関数呼び出しの構文として使用したのだと思いますが、Haskellでは、これは少し違う意味で解釈されます。`func(x,
y)`は、「`func`に`(x, y)`という **タプルを一つ渡す** 」という意味で解釈されます。

実際に二つ（以上）の引数を渡す場合、`func x y`と書くのが正しい構文です。関数名と各引数を空白で空けるだけで良いのです。

これは関数を定義するときも同様です。

恐らく

[code]

    func(x,y) = ...
    
[/code]

という構文を（これまたほかのプログラミング言語に引きずられて）複数の引数を受け取る関数を定義するための構文と勘違いしてしまったようですが、この書き方もやはり、「`func`を
**一つのタプルを受け取る** 関数として定義する」構文となってしまいます。

直す場合、やはり次のようにスペースで関数名と引数を区切る形に書き換えることでできます。

[code]

    func x y = ...
    
[/code]

先ほどの`m`に適用すると、次のように書き換えられます:

[code]

    m [] x=False
    --- (a:as) と、 a:as をカッコで囲わなければならない点に注意！
    m (a:as) x=if x==a then True else m as x
    
[/code]

呼び出すときも余分にタプルで囲わなくなります:

[code]

    > m [100,54,89,27,76,45] 76
    True
    > m [100,54,89,27,76,45]  88
    False
    
[/code]

詳細は割愛しますが、大抵の場合タプルを受け取る・渡す関数を使うより、ここまで紹介した書き方の方が優れています。何より実世界のHaskellのほとんどの関数はこうした形で書かれているので、特別な理由がなければこちらの形に従って頂きたいです。


CC BY-SA 4.0
2020-11-06T03:36:22.510
71762
2020-11-06T03:36:22.510
8007
71760
answer