[英]Deliberately defining infinite type in haskell
我想定義似乎需要無限類型的東西。
必需:一個函數“吃”吃掉它除了“3”之外的所有參數,它返回3
eat 3 = 3
eat x = eat
所以基本上像“吃(+)foldl(Just 5)3”這樣的任意表達式評估為3.但這里的問題是吃的類型。 應該是什么?
我得到的最接近的運行代碼是:
newtype Rec = MakeRec (Int -> Rec)
eat :: Int -> Rec
eat x = MakeRec eat
instance Show Rec where
show _ = "EAT"
這適用於“吃6”而不是“吃6 7”,如果我把(吃3 = 3)放在它的定義中它就不起作用。
我不確定這在Haskell中是否可行。 (用什么論證來表明它是不可能的?)
更新:如下面的解決方案中所述,在編譯時需要類型信息,以便編譯器可以知道“eat foldl 3 foldl”是否無效。 因此,這個問題的確切解決方案是不可能的。
這是不可能的。 在Haskell中顯式禁止無限類型(不是數據類型),並且很容易生成需要它們的代碼,從而產生錯誤(例如, let foo = (42, foo) in foo
嘗試let foo = (42, foo) in foo
)。
當然,您可以使用newtype
和data
創建它們,就像您一樣,但是您必須明確地將值包裝並拆分為構造函數。
這是一個明確的設計決策:對於無限類型,我們希望編譯器拒絕的許多明顯錯誤的表達式必須被允許,並且由於允許更多的程序,許多以前明確類型的程序將變得模糊地鍵入, 1需要顯式類型注釋。 因此需要進行權衡:要求您明確表示無限類型的相當罕見的用途,以換取從類型系統獲得比我們原本更多的幫助。
這就是說,有一種方法可以定義類似的東西eat
功能,使用類型類,但是當你給它不僅可以停止3:你是否已經給它一個3與否只能在運行時確定的,和類型在編譯時決定。 但是,這是一個重載值,既可以是Integer
,也可以是只占用其參數的函數:
class Eat a where
eat :: a
instance Eat Integer where
eat = 3
instance (Eat r) => Eat (a -> r) where
eat _ = eat
問題是您需要在使用時精確指定類型:
*Main> eat 1 foldr ()
<interactive>:6:1:
Ambiguous type variable `t0' in the constraint:
(Eat t0) arising from a use of `eat'
Probable fix: add a type signature that fixes these type variable(s)
In the expression: eat 1 foldr ()
In an equation for `it': it = eat 1 foldr ()
*Main> eat 1 foldr () :: Integer
3
這是因為eat 1 foldr ()
可能是一個Integer
,但也可能是另一個函數,正如我們在同一個表達式中使用eat 1
和eat 1 foldr
函數一樣。 同樣,我們得到靈活的輸入,但必須明確指定我們想要的類型。
1想想類型類重載,比如重載的數字文字( 42
可以是任何類型的Num
實例)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.