kazup0n
ある型クラス(Heap)をラップする型を定義して、それ自体も型クラスのインスタンスにしたいのですが、コンパイルエラーになってしまって悩んでいます。解決策や別実装のアプローチがあればおしえていただきたいです(詳細をスレに書きます)
{-# LANGUAGE ExistentialQuantification #-} -- {-# LANGUAGE ScopedTypeVariables #-} -- {-# LANGUAGE GADTs #-} module Main where class Heap h where insert :: (Ord a) => h a -> a -> h a empty :: (Ord a) => h a isEmpty :: h a -> Bool merge :: (Ord a) => h a -> h a -> h a -- 任意のヒープをラップして別のヒープを構成したい data HW a = forall h. Heap h => Node a (h a) | Empty instance Heap HW where empty = Empty isEmpty Empty = True isEmpty _ = False insert Empty a = Node a Empty insert (Node x h) y = if x > y then Node y (insert h x) else Node x (insert h y) merge Empty h = h merge h Empty = h -- 「h1 h2の型が違う」と怒られる merge (Node a1 h1) (Node a2 h2) = Node (if a1 > a2 then a2 else a1) (merge h1 h2) main :: IO () main = putStrLn "Hello, World!"
• Couldn't match type 'h1' with 'h' Expected: h a Actual: h1 a 'h1' is a rigid type variable bound by a pattern with constructor: Node :: forall a (h :: * -> *). Heap h => a -> h a -> HW a, in an equation for 'merge' at app/Main.hs:29:23-32 'h' is a rigid type variable bound by a pattern with constructor: Node :: forall a (h :: * -> *). Heap h => a -> h a -> HW a, in an equation for 'merge' at app/Main.hs:29:10-19 • In the second argument of 'merge', namely 'h2' In the second argument of 'Node', namely '(merge h1 h2)' In the expression: Node (if a1 > a2 then a2 else a1) (merge h1 h2) • Relevant bindings include h2 :: h1 a (bound at app/Main.hs:29:31) h1 :: h a (bound at app/Main.hs:29:18) | 29 | merge (Node a1 h1) (Node a2 h2) = Node (if a1 > a2 then a2 else a1) (merge h1 h2) | ^^
h1, h2は同じヒープをラップしているかわからないそういうことですね。HWの型にもとのヒープの型を含めるようにしてはどうですか?
data HW h a = Node a (h a) | Empty
instance Heap h => Heap (HW h)
という感じで。-- 任意のヒープをラップして別のヒープを構成したい data HW h a = Node a (h a) | Empty instance Heap h => Heap (HW h) where empty = Empty isEmpty Empty = True isEmpty _ = False insert (Empty) x = Node x empty insert (Node x h) y = if x > y then Node y (insert h x) else Node x (insert h y) merge Empty h = h merge h Empty = h -- 「h1 h2の型が違う」と怒られる merge (Node a1 h1) (Node a2 h2) = Node (if a1 > a2 then a2 else a1) (merge h1 h2)