2012-12-06 19 views
1

造型循環賽調度,當我在建模Haskell這樣的循環調度。非法數據類型的上下文在Haskell

class Schedulable s where 
    isFinal :: s -> Bool 

class Scheduler s where 
    add :: (Schedulable a) => a -> s -> s 
    next :: (Schedulable a) => s -> (a, s) 
    empty :: s -> Bool 

data Schedulable a => RoundRobin = RoundRobin [a] [a] 

instance Scheduler RoundRobin where 
    add p (RoundRobin ps qs) = RoundRobin (ps ++ [p]) qs 

    next (RoundRobin []  qs) = next (RoundRobin qs []) 
    next (RoundRobin (p:ps) qs) = (p, RoundRobin ps (qs ++ [p])) 

    empty (RoundRobin [] _) = True 
    empty _     = False 

然而,GHC抱怨

main.hs:9:6: 
    Illegal datatype context (use -XDatatypeContexts): Schedulable a => 

我怎樣才能解決這個問題呢?

我也看到了a proposal about removing datatype contexts,所以我怎麼能調度程序,而無需使用數據類型的上下文模型?

回答

6

Scheduler

class Scheduler s where 
    add :: (Schedulable a) => a -> s -> s 
    next :: (Schedulable a) => s -> (a, s) 
    empty :: s -> Bool 

是行不通的。任何Schedulable類型的那個值

add承諾可以被添加到所述調度器。這是可能的,但它需要一個擴展,ExistentialQuantificationGADTs或將允許定義一個類型包裝任何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,儘管在約束類型,要求使用該類型的函數上下文。

3

建議不要定義約束到data定義(見Learn Haskell...)。

優選組​​約束上進入功能。

(你可以,反正設定DatatypeContexts修改)

+0

那麼你有什麼建議,我該如何改進我的代碼? –

+0

丹尼爾菲捨爾迴應,當然。但這不是你問的問題...... – josejuan