2017-11-23 9 views
1

現在、カスタム型のいずれかをIntegralに変換できる型クラスを実装しようとしています。インデックスまたはウエイト)。コンパイラはtoIntegralの私の実装のために文句を言うしかしカスタム型のインスタンス化:予想される型 'b'と実際の型 'Int'を一致させることができませんでした。

import Data.Int 

class Convertible a where 
    toIntegral :: Integral b => a -> b 

data Note = Note Tone Int 

instance Convertible Note where 
    toIntegral (Note t o) = o * 12 + toIntegral t 

:この特定のケースで、私は音符が、与えられたオクターブ上で、ピアノのキーボードのキーのインデックスに変換できることを確認するためにそれを使用したいですNoteは私のConvertibleのtypeclassに従っていません。

• Couldn't match expected type ‘b’ with actual type ‘Int’ 
    ‘b’ is a rigid type variable bound by 
    the type signature for: 
     num :: forall b. Integral b => Note -> b 
    at src/Note.hs:11:5 
• In the expression: octave * 12 + (num tone) 
    In an equation for ‘num’: 
     num (Note tone octave) = octave * 12 + (num tone) 
    In the instance declaration for ‘Convertible Note’ 
• Relevant bindings include 
    num :: Note -> b (bound at src/Note.hs:11:5) 

私の知る限り理解し、それは私のtoIntegral機能の内容は、私がIntegral => b -> a -> bすることを制約a -> Int、と評価されたと見なします。今私は何が間違っているの理解していないIntIntegral typeclassを実装している、右か?

私が明らかに間違っていることを理解できたら助けてくれますか?

答えて

2

タイプ変数は、呼び出し先によって選択され、呼び出し先では選択されません。あなたの場合、toIntegralbを選択できません。その発信者はbを選択できません。その種類によると、これらの用途の全てはとても任意の整数bを返すために、

toIntegral (Note t o) :: Int 
toIntegral (Note t o) :: Integer 
toIntegral (Note t o) :: Word32 
-- etc. 

ソリューションはoを変換するだけでなく、すなわちをInt Sを変換することで型チェックだけではなく、Intなければなりません。

たとえば、fromIntegral oは、タイプに変換することができます。したがって、Integralになります。

とにかく、toIntegralに本当にそのタイプが必要ですか?

+1

確かに、あなたは 'Integral'クラスから' fromIntegral'を意味します。 :D – gallais

+0

@gallais私はそれが今修正されるべきだと思います。いつものように、数値変換はHaskellではややこしいことです。私が変換を実行するために見ることができる唯一の方法は、少し複雑だと感じる「Integer」を使うことです。私は 'toEnum'がそれと同等であることが保証されているのだろうかと思います。 – chi

+2

私はかなり確かに 'toIntegral(ノートt o)= fromIntegral o * 12 + toIntegral t'はうまくいくでしょう。 – gallais

関連する問題