2017-07-14 13 views
4

Typed holes提供了一個找到如何實現某些東西的好方法:如果你知道使用什麼函數,比如說foo,那麼你可以寫出類似foo _ _ _的東西,並讓編譯器告訴你它對每個參數需要什麼類型。這使得查詢任何文檔基本上沒有必要。什麼是快速確定給一個函數輸入多少個孔的方法?

但是,如果您實際寫出下劃線的正確號碼,它纔會正常工作。目前,我通常通過一些試驗性的方法來確定這一點,但並不總是顯而易見的,因爲在Haskell中,函數總是可以部分應用。

什麼是儘快找出這個號碼的好方法?

+0

@hnefatl我認爲,在Haskell類別中具有金色徽章的人知道':type'命令... :)但問題是關於爲某些函數找到正確數量參數的快速方法。對我來說,打開'ghci',使用'foo'函數加載模塊,然後打印':t foo'可能會慢得多,只是嘗試添加下劃線並查看運行'ghcid'守護進程的結果。 – Shersh

+9

也許一種快速獲得'foo'類型的方法可能會寫'_ foo'並查看洞的類型。儘管可能有些類似IDE的幫助會更好。 – chi

+0

我同意@chi,你可能想使用IDE功能來做到這一點。輸入'foo'並將其懸停在其上以查看它的類型。我想這仍然需要你認真思考foo的類型和你想要的結果的類型,例如,你會部分應用'foo'。如果你輸入'_'而不是'foo',那麼在什麼情況下ghci建議'foo'的類型是相關的? –

回答

1

正如@chi所說,我發現的最好的東西是「在功能上應用洞」。我不知道這是否回答了這個問題,但希望它至少有點幫助。

我猜,由「功能總是可以只是部分應用」你的意思是你可以有這樣的功能:

foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b 
foldr = undefined 

爲這你不能僅僅從多少爭論它的類型告訴應該採取任何特定類型的類型檢查。該typechecker可以在這裏做的最好的是要告訴你的參數的最小數目將接受:

bar :: String -> String 
bar = _1 foldr 

* Found hole: 
    _1 :: ((a0 -> b0 -> b0) -> b0 -> t0 a0 -> b0) -> String -> String 
    Where: `t0' is an ambiguous type variable 
     `b0' is an ambiguous type variable 
     `a0' is an ambiguous type variable 
* In the expression: _ 
    In the expression: _ foldr 
    In an equation for `bar': bar = _ foldr 

* Ambiguous type variable `t0' arising from a use of `foldr' 
    prevents the constraint `(Foldable t0)' from being solved. 
    Probable fix: use a type annotation to specify what `t0' should be. 
    These potential instances exist: 
    instance Foldable (Either a) -- Defined in `Data.Foldable' 
    instance Foldable Maybe -- Defined in `Data.Foldable' 
    instance Foldable ((,) a) -- Defined in `Data.Foldable' 
    ...plus one other 
    ...plus 22 instances involving out-of-scope types 
    (use -fprint-potential-instances to see them all) 

旁白:第二個錯誤是不是特別有幫助這裏,因爲t0可能真的是這些類型的任何。但是如果你經常遇到這種情況,那麼-fprint-potential-instances實際上可能會有用。

你現在可以做的類型檢查的一點點在你的腦袋:

((a0 -> b0 -> b0) -> b0 -> t0 a0 -> b0 ) -> 
    <_1>    <_2> String -> String 

的類型相匹配,則必須提供至少兩個孔。您可能需要更多,但這取決於b0的實例化。在這些孔代,你會得到一個非常簡單的問題

bar :: String -> String 
bar = foldr _1 _2 

* Found hole: _1 :: Char -> String -> String 

* Found hole: _2 :: String 

你甚至可能會遇到一個(在我看來,傻)之類的函數

class C a where foo :: a 
instance C String where 
instance C a => C (Int -> a) where 

在這種情況下,你可以這樣做事情,並typechecker有用地通知你所有可能的情況:

bar :: String -> String 
bar = _ foo 

test0.hs:6:7: warning: [-Wtyped-holes] 
    * Found hole: _ :: t0 -> String -> String 
     Where: `t0' is an ambiguous type variable 
    * In the expression: _ 
     In the expression: _ foo 
     In an equation for `bar': bar = _ foo 
    * Relevant bindings include 
     bar :: String -> String (bound at test0.hs:6:1) 

test0.hs:6:9: warning: [-Wdeferred-type-errors] 
    * Ambiguous type variable `t0' arising from a use of `foo' 
     prevents the constraint `(C t0)' from being solved. 
     Probable fix: use a type annotation to specify what `t0' should be. 
     These potential instances exist: 
     instance C a => C (Int -> a) -- Defined at test0.hs:3:10 
     instance C String -- Defined at test0.hs:2:10 
    * In the first argument of `_', namely `foo' 
     In the expression: _ foo 
     In an equation for `bar': bar = _ foo 

在這裏你真的要克UESS。在這個(不可否認的)例子中,我可能會猜想你想要一個參數,因爲bar需要一個參數。

bar :: String -> String 
bar = foo . _ 

test0.hs:6:7: warning: [-Wdeferred-type-errors] 
    * Ambiguous type variable `b0' arising from a use of `foo' 
     prevents the constraint `(C (b0 -> String))' from being solved. 
     (maybe you haven't applied a function to enough arguments?) 
     Probable fix: use a type annotation to specify what `b0' should be. 
     These potential instance exist: 
     instance C a => C (Int -> a) -- Defined at test0.hs:3:10 

test0.hs:6:13: warning: [-Wtyped-holes] 
    * Found hole: _ :: String -> b0 
     Where: `b0' is an ambiguous type variable 

現在,它會告訴你有一個潛在的實例,所以你可以猜測,該孔的類型真的應該String -> Int

相關問題