我正在研究一個包含monoid的applicative函數來「查看」執行。然而,有時候我根本不關心這個部分,所以幺半羣的選擇是不相關的,因爲它永遠不會被消耗。我已經簡化我有什麼到:使用約束類型和類型族具有「受限制」的約束
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
import GHC.Exts
class Render a b where render :: a -> b
instance Render a() where render = const()
class Merge a where
type Renderer a b :: Constraint
merge :: Renderer a b => a -> b
data Foo = Foo Bool
instance Merge Foo where
type (Renderer Foo) m = (Render Bool m)
merge (Foo b) = render b
Render
用於各種a
轉換且爲單一b
。 Merge
是我的實際仿函數的一個很大的簡化,但重點是它包含一個類型族/約束,我的目的是明確指定什麼Render
和Merge
需要。現在
,我可能要「跑」的Merge
,但丟棄的觀點,這是類似於這樣的:
runFoo :: Merge a => a -> Int
runFoo x = case merge x of() -> 5
但因爲這將失敗:
無法推斷
(Renderer a())
從使用merge
我選擇()
我的幺因爲˚F產生或者a
,我們有一個Render a()
的實例。所以如果有一種方法可以說Merge a
只是意味着收集Render
約束,那麼這將工作正常。當然,Merge a
比這更一般 - 它可以添加任意約束,這就解釋了編譯錯誤。
有沒有辦法實現我想要的沒有更改runFoo
的簽名?
是否'Renderer'總是正好包括一個'Render'? – 2013-01-04 13:55:21
@Tinctorius - 不,通常取決於'Foo'字段中不同類型的數量 – ocharles
'Merge'沒有'b'作爲參數嗎? –