你Scheduler
類
class Scheduler s where
add :: (Schedulable a) => a -> s -> s
next :: (Schedulable a) => s -> (a, s)
empty :: s -> Bool
是行不通的。任何Schedulable
類型的那個值
add
承諾可以被添加到所述調度器。這是可能的,但它需要一個擴展,ExistentialQuantification
GADTs
或將允許定義一個類型包裝任何Schedulable
值。
next
,然而,承諾提供的任何Schedulable
類型的值,無論主叫慾望,而不是去上班。如果我只將Int
的值添加到調度程序中,然後請求String
,它將如何構建一個簡潔的空氣?
一個辦法讓你的代碼工作是
{-# LANGUAGE GADTs #-}
module Schedules where
class Schedulable s where
isFinal :: s -> Bool
class Scheduler s where
add :: (Schedulable a) => a -> s -> s
next :: s -> (Schedule, s) -- returns a Schedulable item of unknown type, wrapped in a Schedule
empty :: s -> Bool
-- Wrapper type for any Schedulable
data Schedule where
Schedule :: Schedulable a => a -> Schedule
-- Equivalent alternative using existential quantification instead of GADT syntax
-- data Schedule = forall a. Schedulable a => Schedule a
-- make Schedules Schedulable, maybe not necessary
instance Schedulable Schedule where
isFinal (Schedule s) = isFinal s
-- RoundRobin queues schedulable items, wrapped as Schedules, since lists are homogeneous
data RoundRobin = RoundRobin [Schedule] [Schedule]
-- How RoundRobin works
instance Scheduler RoundRobin where
-- enqueue item after wrapping it
add p (RoundRobin ps qs) = RoundRobin (ps ++ [Schedule p]) qs
-- deliver next item to process
-- the first equation suggests that (Maybe Schedule, s) would be the better return type
next (RoundRobin [] []) = error "Nothing to schedule"
next (RoundRobin [] qs) = next (RoundRobin qs [])
next (RoundRobin (p:ps) qs) = (p, RoundRobin ps (qs ++ [p]))
empty (RoundRobin [] _) = True
empty _ = False
使用GADT
語法或存在量化使得強加於通過模式匹配可用的構造函數的約束,相反,老DatatypeContexts
,儘管在約束類型,要求使用該類型的函數上下文。
那麼你有什麼建議,我該如何改進我的代碼? –
丹尼爾菲捨爾迴應,當然。但這不是你問的問題...... – josejuan