举个例子,我想实现这样的东西:
someWrite :: IORef a -> a -> IO ()
someWrite = writeIORef
someWrite :: Eq a => IORef a -> a -> IO ()
someWrite ref value = do
oldValue <- readIORef ref
if oldValue == value
then putStrLn "Did not write"
else writeIORef ref value
显然,该代码是非法的。这样的事怎么能做?
那么,这个怎么样:
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, KindSignatures, FunctionalDependencies, UndecidableInstances, TypeFamilies, ScopedTypeVariables #-}
import Data.IORef
data HTrue
data HFalse
class SomeWrite a where
someWrite :: IORef a -> a -> IO ()
class SomeWrite' f a where
someWrite' :: f -> IORef a -> a -> IO ()
instance (Pred f a, SomeWrite' f a) => SomeWrite a where
someWrite = someWrite' (undefined::f)
class Pred f a | a -> f where {}
instance (f ~ HTrue) => Pred f a
instance Pred HFalse Bool
instance Pred HFalse String
-- Add the rest here
instance SomeWrite' HTrue a where
someWrite' _ = writeIORef
instance Eq a => SomeWrite' HFalse a where
someWrite' _ ref value =
do
oldValue <- readIORef ref
if oldValue == value
then putStrLn "Did not write"
else writeIORef ref value
https://wiki.haskell.org/GHC/AdvancedOverlap描述了执行此操作的方法。