0
這裏的代碼片段:如何處理haskell中同一類的返回值?
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
module Main
where
import Control.Exception
import System.IO
main :: IO()
main = putStrLn "Hello World"
class IConn a where
execute :: a -> IO()
delete :: a -> IO()
data ConnA = ConnA
instance IConn ConnA where
execute _ = putStrLn "Execute A"
delete _ = putStrLn "Delete A"
data ConnB = ConnB
instance IConn ConnB where
execute _ = putStrLn "Execute B"
delete _ = putStrLn "Delete B"
class IConn (Conn b) => IBackend b where
type Conn b :: *
create :: b -> IO (Conn b)
withConn :: b -> Int -> Int -> (Conn b -> IO a) -> IO a
withConn b l u f = do
putStrLn $ "low: " ++ show l
putStrLn $ "up: " ++ show u
bracket (create b) delete f
data BackendA = BackendA
data BackendB = BackendB
instance IBackend BackendA where
type Conn BackendA = ConnA
create _ = return ConnA
instance IBackend BackendB where
type Conn BackendB = ConnB
create _ = return ConnB
data Backend = forall b. IBackend b => Backend b
func :: IConn c => c -> IO()
func c = do
putStrLn "Beginning of func."
execute c
putStrLn "end of func."
createBackend :: String -> IO Backend
createBackend "A" = return $ Backend BackendA
createBackend "B" = return $ Backend BackendB
test :: String -> IO()
test name =
createBackend name >>= \case
Backend imp
-> withConn imp 10 100 func
如果我不包裝在數據Backend
返回由createBackend
的IBackend
,該createBackend
功能將無法編譯。但現在我必須使用test
函數中的case語句從Backend
取消箱IBackend
。這有點麻煩。任何改善test
或createBackend
功能的建議?
做'createBackend'和'test'必須採取一個字符串作爲參數?如果可能的話,如果可能的話,更好的辦法是讓它們採用一個單一的GADT類型'SBackend b'來標識想要的後端,即使在類型級別,這樣就不再需要存在的包裝器'Backend'。根據您的使用情況,這可能是不可能的。 – chi