![](/img/trans.png)
[英]Creating a typeclass that returns another instance of that typeclass in haskell
[英]Typeclass method which returns another typeclass in Haskell
我必須在Haskell中定義2個類型類。 一種很簡單-它實現了Ord,並且具有一種將給定類型轉換為int的方法。 像這樣:
class (Ord a) => Id a where
toInt :: a -> Int
which has a method . 但是然后我有了另一個具有方法的類型類 。 typeclass. 此方法應返回類型類。 所以我寫了這樣的東西:
class HasId a where
getId :: a -> Id a
我收到一個我不知道如何解決的錯誤。
• Expected kind ‘* -> Constraint’, but ‘Int’ has kind ‘*’
• In the class declaration for ‘HasId’
|
| class (Int a) => HasId a where | ^^^^^
• Expected a type, but ‘Id a’ has kind ‘Constraint’
• In the type signature: getId :: a -> Id a
In the class declaration for ‘HasId’
|
| getId :: a -> Id a |
有人可以告訴我如何在另一個人的typeclass方法中返回typeclass嗎? typeclass at first? 我應該首先實現類型類的某些實例嗎?
要明白,一個Haskell是很重要的class
是在面向對象的語言類非常不同的。 這是一個類型類 ,即它“將類型的集合分組在一起”,而OO類將值的集合分組在一起。 IOW,OO類是一種類型(包含值),但是Haskell類實際上是某種類型的類型 。
現在,函數/方法始終將值作為參數,並返回值作為結果。 但是它不能給您返回類型,也不能給您“類型類的值”,因為沒有這種東西。
相反,使用類型類的方式是這樣的:編寫一個多態函數 ,即一個接受或產生未指定類型的值的函數。 這就是類型變量的用途。 通常,多態簽名意味着函數可以處理任何類型的值,例如
length :: [a] -> Int
它接受一個列表,並不關心其元素的類型。 但是然后您說您確實在乎使用了什么類型,即,您要求它們在類中。 這是一個約束 ,它是用=>
表示法編寫的。 toInt
實際上具有簽名(由類聲明自動生成)
toInt :: Id a => a -> Int
坦白說,我懷疑這真的是您想要的。 如果你可以用做Id a
是將其轉換為Int
,那么結果是一個有效的Int
(只是一個類型的注釋這表明什么樣的對象的此ID屬於),而不管的a
參數。 因此,您應該考慮使用Id
類型來代替Id
類
newtype Id' a = Id {toInt :: Int} -- The prime ' symbol has no particular meaning,
-- I just use it for disambiguation.
然后,你有更明智的類型
toInt :: Id' a -> Int
不需要任何限制。
newtype
與OO類非常相似,因為它實際上定義了一個具體類型,該類型具有可以傳遞的值。
getId
方法也是一個受約束的多態函數,它可以接受“具有Id
”並返回給您該Id的內容。 在這種情況下,一個類是有意義的(因為您可以具有不同的數據結構,這些數據結構可能以不同的方式存儲其ID)。 現在實際上是
class HasId a where
getId :: a -> Id' a
根據Welperooni的回答 ,使用原始Id
類定義HasId
確實也是可以HasId
,只是這實際上沒有多大意義。 Id
是可用作 Id
的所有類型的類 。 您可以表示getId
可以產生任何這種類型的ID:
class HasId a where
getId :: Id b => a -> b
請注意,result-Id類型現在完全獨立於您要計算其ID的對象的類型。 b
可以始終是任何 Id類型。 就像我說的那樣,這沒有任何意義:為什么您需要大量代表Ids的不同類型,卻需要所有HasId
類型來支持所有這些類型?
實際上,這無法按現狀實現,因為沒有機制可以讓您生成任意Id
類型的Id
。 這將需要其他方法
class Id a where
toInt :: a -> Int
fromInt :: Int -> a
現在你可以做
class HasId a where
getId :: Id b => a -> b
data SomeObj { objName :: String
, objId :: Int }
instance HasId SomeObj where
getId (SomeObj _ i) = fromInt i
但是,如果您要求任何Id
類型都可以從Int
轉換為Int
,則這些類型必須與Int
本身同構。 因此, newtype Id' a
方法幾乎可以肯定更好。
您將返回值聲明為HKT Id a
,但您想要的是另一種類型,受類型類Id
約束。
您需要的不是getId :: a -> Id a
,而是getId :: Id b => a -> b
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.