[英]Haskell: Function as Data type
我覺得學習haskell的思維障礙之一是data
有時將功能定義為數據。
data Person = Person {
name :: String,
age :: Int
}
這是直觀的,類似於其他語言。 但在
newtype StateT s m a = StateT {
runStateT :: s -> m (a,s)
}
這基本上是在調用函數s->m (a,s)
“數據”
我很容易理解,在高階函數中,“函數”確實作為數據傳遞。 但是在類型定義中,使用函數定義類型是非常令人驚訝的。
所以我的問題是:這會給Haskell類型系統帶來表現力嗎? 所有這些背后的理論是什么?
這只是圍繞一個功能的包裝。
foo :: String -> [(Int, String)]
foo xs = zip [1..] (map pure xs)
fooState :: StateT String [] Int
fooState = StateT foo
數據構造函數StateT
接受一個參數,即類型s -> m (a, s)
的函數,並返回StateT sma
類型的值。 在這里,我們有
s ~ String
m ~ []
a ~ Int
由於foo
的聲明類型。
與Python這樣的語言中的函數引用確實沒有太大區別。 (請注意,此處的foo
類型與Haskell示例中的類型略有不同,但是要注意將foo
的引用傳遞給StateT.__init__
的想法)。
class StateT:
def __init__(self, f):
self.runStateT = f
def foo(xs):
return enumerate(xs)
x = StateT(foo)
函數與其他任何值一樣,具有類型,並且可以將其作為參數傳遞。 數據類型的字段也可以存儲函數,這又與使用其他值沒有什么不同:
GHCi> :t ("foo", "bar")
("foo", "bar") :: ([Char], [Char])
GHCi> :t (reverse, drop 2)
(reverse, drop 2) :: ([a1] -> [a1], [a2] -> [a2])
從這個角度來看,...之間沒有本質區別。
newtype MyInt = MyInt { getMyInt :: Int }
...和:
newtype StateT s m a = StateT { runStateT :: s -> m (a,s) }
這會為Haskell類型系統帶來表現力嗎?
這是這樣做的兩種方法。 首先,函數類型的包裝和類型同義詞允許編寫較少混亂的類型簽名。 例如...
withStateT :: (s -> s) -> StateT s m a -> StateT s m a
...比以下內容好得多:
withStateT :: (s -> s) -> (s -> m (a, s)) -> (s -> n (a, s))
其次,新型包裝器使為函數類型編寫類實例變得可行-例如,沒有它們,我們將沒有StateT
擁有的至關重要的實例( Functor
, Applicative
, Monad
, MonadTrans
等)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.