もっと一般的なコードを書く方法を学ぶために、私は という簡単なArrayクラスを書こうとしました。考え方は、単純な配列操作 だけをArrayクラスが提供する関数で記述し、異なるデータ型をインスタンスとして記述することです。 だから私は配列の異なる表現を書いてみたいです。なぜGHCはFoldableにベクターを「アップキャスト」しないのですか?
最初の試みとして、配列にはいくつかの行と列と折り畳み可能なコンテナがあります。
module Array where
import qualified Data.Vector as V
import Data.Foldable
class Array arr where
aRows :: arr a -> Int
aCols :: arr a -> Int
aData :: Foldable t => arr a -> t a
data VectorArray a = VectorArray
{ vRows :: !Int
, vCols :: !Int
, vData :: !(V.Vector a)}
instance Array VectorArray where
aRows = vRows
aCols = vCols
aData = vData
最後の行はコンパイルされません:
• Couldn't match type ‘t’ with ‘V.Vector’
‘t’ is a rigid type variable bound by
the type signature for:
aData :: forall (t :: * -> *) a. Foldable t => VectorArray a -> t a
at src/Array.hs:19:5
Expected type: VectorArray a -> t a
Actual type: VectorArray a -> V.Vector a
• In the expression: vData
エラーメッセージの私の解釈:あなたは(プログラマが)私にV.Vector
Aを与えるが、私(GHCコンパイラが) がt a
たいt
は、Foldableクラスのインスタンスである必要があります。
今、V.VectorはFoldableのインスタンスです。だから私は、インスタンスとして Foldableを引数として渡さなければならないすべての関数で、タイプV.Vectorの値を使用できます。 私の質問は:GHCがなぜアップキャストされないのですかV.Vector〜Foldable?例がありますか? そのようなアップキャストは問題の原因となるでしょうか?
PS:上記のエラーを回避するには、aData
関数をArrayクラス から削除し、VectorArrayをFoldableのインスタンスにします。
実存的なタイプの議論は良いですが、答えは非常にスタートが、それはOPのように聞こえますコード*はハスケルだけがアップキャストをサポートしていれば動作します。ここでの問題は、Haskellがアップキャストをサポートしていないことではなく、OPがアップキャストしようとしているタイプが、実際に彼らが望むタイプのスーパータイプではないので、ここでアップキャストすることは有効ではないということですからアップキャスト。 (そして、Haskellがサブタイプ化しているのは、より多態型のインスタンスである型だけで、それは "アップキャスト"をサポートしています)。 – Ben