6

私はHaskellにかなり慣れていないので、これがばかげた質問ではないことを願っています。私はこのデータ型を持っています:

data N = I Int | D Double deriving (Show, Eq)

(Num a) => (a -> a -> a) -> N -> N -> Ns内の数値に関数を適用Nし、結果とともにNを返すシグネチャを使用して関数を作成しようとしています。Nsが両方ともsの場合は、関数を適用して;Dを返す必要があります。D一方がanIで、もう一方がaの場合、 inをaにD変換し、関数を2つのsに適用して、 ;を返す必要があります。両方がsの場合、関数を適用して。を返す必要があります。これが私がこれまでに持っている(壊れた)コードです:IntIDoubleDoubleDII

widen :: N -> N -> (N, N)
widen (I i) d@(D _) = (D (fromIntegral i), d)
widen d@(D _) i@(I _) = widen i d
widen x y = (x, y)

numOp :: (Num a) => (a -> a -> a) -> N -> N -> N
numOp op x y = case widen x y of (D x', D y') -> D $ x' `op` y'
                                 (I x', I y') -> I $ x' `op` y'

ただし、の両方の行でエラーが発生しnumOpます。最初のものは次のとおりです。

Could not deduce (a ~ Double)
from the context (Num a)
  bound by the type signature for
             numOp :: Num a => (a -> a -> a) -> N -> N -> N
  at <line num>
In the second argument of `($)', namely x' `op` y'
In the expression: D $ x' `op` y'
In a case alternative: (D x', D y') -> D $ x' `op` y'

そして2番目:

Couldn't match type `Double' with `Int'
Expected type: Int
  Actual type: a
In the second argument of `($), namely x' `op` y'
In the expression: I $ x' `op` y'
In a case alternative: (I x', I y') -> I $ x' `op` y'

両方のエラーの意味を理解していると確信しています。最初の1つは、型シグネチャの情報では、GHCが値コンストラクターに必要なをop返すと想定するのに十分ではないと言っていると思います。2つ目は、最初の行がそれを意味するので、これは行は、型の値を。のように使用することはできません。しかし、これを行う正しい方法をどこから探し始めるのかわかりません。DoubleDaDoubleaInt

それが役に立ったら、これを機能させようとしている理由は、Write YourselfaSchemeチュートリアルに沿ってフォローしているからです。チュートリアルのすべての例(特に評価セクション)は整数のみを扱いますが、演習として、整数と浮動小数点数の両方をサポートする機能を追加して、たとえば(+ 1 2.5 2.5)が戻る6.0(+ 1 2 3)戻るようにします6。私がこれを間違った方法で考えている場合、またはそれを達成するためのより簡単な方法がある場合は、提案を聞いてみたいです。

4

1 に答える 1

7

サイン

numOp :: (Num a) => (a -> a -> a) -> N -> N -> N

は、と2つの特定のインスタンスごとに型の単形関数をnumOp取り、そこからを計算すると言います。したがって、たとえば、タイプの関数a -> a -> aNumNN

Complex Float -> Complex Float -> Complex Float

また

approxRational :: RealFrac a => a -> a -> Rational

(に特化a = Rational)は、正当な最初の引数になります。

必要なのは、すべてのNumインスタンスを最初の引数として処理できるポリモーフィック関数、つまりランク2タイプです。

numOp :: (forall a. Num a => a -> a -> a) -> N -> N -> N

RankNTypes(そのための言語拡張が必要です)。

于 2012-12-31T01:29:13.020 に答える