簡體   English   中英

Haskell:作為數據類型

[英]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擁有的至關重要的實例( FunctorApplicativeMonadMonadTrans等)。

暫無
暫無

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

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