haskell-jp / questions #102 at 2022-11-08 21:18:51 +0900

↑ の続きの質問です。 `RMQ (ST S)` と `RMQ IO` を両方 `SegmentTree` のインスタンスにしたいのですが、エラーが出て困っております。
1. .. の場合>: Illegal type synonym family application のエラーが出ます。
2. : 2 つの実装の範囲が重なっていてエラーが出ます。
この件どう直せば良いでしょうか……? m(_ _)m
そもそも,おなじ `primstate` に対して, `primstate ~ PrimState m` となるような `PrimMonad` である `m` はたくさん存在する,と言うのが問題ですよね.例えば,`primstate ~ RealWorld` の時点で

```PrimState (ST RealWorld) = RealWorld
PrimState IO = RealWorld
PrimState (MaybeT IO) = RealWorld```
`IO` と `ST` の時点で重複があるので, `M RealWorld` を一つに定めるのは不可能です.ふつうに `ST RealWorld` を使うこともありますしね.だから, `M primstate` という型族を用いるのが良くないのでは,という気がしています.

例えば:

```{-# LANGUAGE MultiParamTypeClasses #-}
class Monad m => SegmentTree a m where
updateParent :: a -> Int -> Int -> m Int
....

instance PrimMonad m => SegmentTree (RMQ (PrimState m)) m where ...```
とか,

```{-# LANGUAGE MultiParamTypeClasses #-}
class Monad m => SegmentTree a m where
updateParent :: a -> Int -> Int -> m Int
....

instance SegmentTree (RMQ s) (ST s) where ...
instance SegmentTree (RMQ RealWorld) IO where ...```
とか,

```class SegmentTree f where
updateParent :: PrimMonad m => f (PrimState m) -> Int -> Int -> m Int
...

instance SegmentTree RMQ where ...```
とか.

また,コードでは `RMQ s` とか `RMQ RealWorld` とかやって使うようになっていますが,質問文のように `RMQ IO` とか `RMQ (ST s)` とかやって使うとすれば:

```class SegmentTree f where
updateParent :: PrimMonad m => f m -> Int -> Int -> m Int
...

instance SegmentTree RMQ where ...```
とかもあります.`RMQ RealWorld` バージョン にも私が思いつくだけで変種が三種類ありましたが, `RMQ IO` バージョンにも同じような変種がありますね.
gksato さん! いつも C++ よりも速いお姿を拝見しております。あれは Haskell っていう言語なのですか……? ()
IOST の時点で重複があるので, M RealWorld を一つに定めるのは不可能です.
それなら関連型 (型族?) ではなく型パラメータを取らないといけませんね。`updateParent :: PrimMonad m => ..` の形が良いと思いました。ありがとうございます。