[英]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.