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)