簡體   English   中英

故意在haskell中定義無限類型

[英]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 )。

當然,您可以使用newtypedata創建它們,就像您一樣,但是您必須明確地將值包裝並拆分為構造函數。

這是一個明確的設計決策:對於無限類型,我們希望編譯器拒絕的許多明顯錯誤的表達式必須被允許,並且由於允許更多的程序,許多以前明確類型的程序將變得模糊地鍵入, 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 1eat 1 foldr函數一樣。 同樣,我們得到靈活的輸入,但必須明確指定我們想要的類型。

1想想類型類重載,比如重載的數字文字( 42可以是任何類型的Num實例)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM