2010-07-03 80 views
4

這裏是我的嘗試至今:約束返回類型的上下文

module Main where 

data FooT = One | Two deriving (Show, Read) 
{- 
That is what I want 
foo :: (Show a, Read a) => a 
foo = One 
-} 

--class Footable (Show a, Read a) => a where 
class Footable a where 
    --foo2 :: (Show a, Read a) => a 
    foo2 :: a 

instance Footable FooT where 
    foo2 = One 

-- test = print foo2 

我想測試編譯。我不認爲這個問題圍繞着普遍的量化而展開。 GHC說,一個是一個「嚴格的類型變量」 編輯剛性類型的變量),但我真的不理解這是什麼。這個問題似乎正如我在我的評論@寫sepp2k它可能對生存型,但我無意中發現了一個奇怪的行爲可能與this

編輯

確實編譯:

{-# LANGUAGE OverlappingInstances, FlexibleInstances, OverlappingInstances, 
UndecidableInstances, MonomorphismRestriction, PolymorphicComponents #-} 
{-# OPTIONS_GHC -fno-monomorphism-restriction #-} 

module Main where 

    class (Num a) => Numable a where 
     foo2 :: a 

    instance (Num a) => Numable a where 
     foo2 = 1 

    instance Numable Int where 
     foo2 = 2 

    instance Numable Integer where 
     foo2 = 3 

    --test = foo2 + foo2 -- This does NOT compile (ambiguous a) 
    test = (foo2::Integer) + foo2 --this works 

但這並不(`a」是剛性類型的變量消息)

{-# LANGUAGE OverlappingInstances, FlexibleInstances, OverlappingInstances, 
UndecidableInstances, MonomorphismRestriction, PolymorphicComponents #-} 
{-# OPTIONS_GHC -fno-monomorphism-restriction #-} 

module Main where 

    data FooT = One | Two deriving (Show, Read) 
    data BarT = Ten deriving (Show, Read) 

    class (Show a, Read a) => Footable a where 
     foo2 :: a 

    instance (Show a, Read a) => Footable a where 
     foo2 = Ten 

    instance Footable FooT where 
     foo2 = One 

    main = print foo2 

這是因爲1 ::(Num t)=> t。我可以像這樣定義一些東西(typeconstructor,consts dunno)嗎?

+0

反引號不起作用格式化的多行代碼。您必須縮進四個空格(或使用代碼按鈕或Ctrl-K)。 – sepp2k 2010-07-03 10:27:19

+0

和撇號混亂的配色方案。但現在很好。 – supertux 2010-07-03 10:35:11

+1

你應該真的開始發佈整個錯誤消息。該消息的重要組成部分,是「無法匹配預期型'一個」反推斷類型'巴特」,而不是‘一個是剛性類型變量...’(不描述錯誤 - 它只是告訴你一個地方來自)。 – sepp2k 2010-07-03 15:13:51

回答

5

當我取消的test的定義,並嘗試編譯代碼時,我得到「曖昧類型變量」。沒有什麼嚴格的。要理解爲什麼這是不明確的考慮:

module Main where 

data FooT = One | Two deriving (Show, Read) 
data BarT = Three | Four deriving Show 

class Footable a where 
    foo2 :: a 

instance Footable FooT where 
    foo2 = One 

instance Footable BarT where 
    foo2 = Three 

main = print foo2 -- Should this print One or Three? 

當然,在你的代碼中有Footable只有一個實例,所以哈斯克爾在理論上可以推斷出你想要使用的定義foo2FooT,因爲這是唯一的實例在適用範圍。但是如果這樣做,該代碼將盡快爲您導入的情況來定義Footable的另一個實例模塊摔壞,所以Haskell沒有做到這一點。

要解決你的問題,你需要用它的類型來註釋foo2的,像這樣:

module Main where 

data FooT = One | Two deriving (Show, Read) 

class Footable a where 
    foo2 :: a 

instance Footable FooT where 
    foo2 = One 

main = print (foo2 :: FooT) 

要求所有Footables是顯示和閱讀的情況下,簡單地做:

class (Show a, Read a) => Footable a where 
    foo2 :: a 

像你這樣在你的評論中,但沒有再次在foo2的簽名中指定約束。

+0

我的想法是,如果我以這種方式限制foo foo ::(Show a,Read a)=>我可以返回各種類型而不違反類型安全性。 (當你取消註釋函數foo時,會彈出'strict type-variable')。我的班級Footable是一個試圖解決問題的嘗試。我需要的是存在型或類型族。 – supertux 2010-07-03 11:00:56

+0

當您執行'main = print 3'時,它會將'3'專用於'Integer'類型(即使只需要'(Num a,Show a)')。可能有一些方法來定義「默認值」 – ony 2010-07-03 12:31:01

+2

@ony:沒有辦法爲用戶定義的類型類定義默認值。 – sepp2k 2010-07-03 12:36:24

2

正如sepp2k說,GHC無法猜測foo2的返回類型。做它的約束(這是你的問題的標題)添加一個內聯類型的簽名。

測試=打印(foo2的::英尺)

+0

:: FooT不限制上下文,但聲明foo2的類型爲FooT – supertux 2010-07-04 20:01:19

+0

這就是我們想要的,不是嗎? – mb14 2010-07-04 20:12:09