如何派生Haskell记录字段的类型?

Ole*_*leg 6 monads haskell

来自OOP这对我来说似乎是外星代码.

我不明白为什么类型runIdentity是一个函数:

runIdentity :: Identity a -> a?我指定是runIdentity :: a

newtype Identity a = Identity {runIdentity :: a} deriving Show

instance Monad Identity where
  return = Identity
  Identity x >>= k = k x

instance Functor Identity where
  fmap  f (Identity x) = Identity (f x)

instance Applicative Identity where
  pure = Identity
  Identity f <*> Identity v = Identity (f v)

wrapNsucc :: Integer -> Identity Integer
wrapNsucc = Identity . succ
Run Code Online (Sandbox Code Playgroud)

致电runIdentity:

runIdentity $ wrapNsucc 5 - 输出6作为输出

Phi*_*ner 10

你是对的,这runIdentity只是一个简单的类型领域a.但类型runIdentityIdentity a -> a,既然runIdentity是一个函数,以提取出现场的Identity a.runIdentity毕竟,在没有提供值的情况下,你无法获得价值.

编辑:要在评论中稍微扩展一下OOP类比,请考虑一个类

class Identity<T> {
    public T runIdentity;
}
Run Code Online (Sandbox Code Playgroud)

这是Identitymonad,松散地翻译成OOP代码.模板参数T基本上是你的a; 因此,runIdentity属于类型T.要从T你的对象那里得到它,你可能会做类似的事情

Identity<int> foo = new Identity<int>();
int x = foo.runIdentity;
Run Code Online (Sandbox Code Playgroud)

你认为runIdentity它是一种类型T,但事实并非如此.你不能这样做

int x = runIdentity; // Nope!
Run Code Online (Sandbox Code Playgroud)

因为 - runIdentity从哪里获得?相反,想到这就像做

Identity<int> foo = new Identity<int>();
int x = runIdentity(foo);
Run Code Online (Sandbox Code Playgroud)

这显示了当你打电话给会员时实际发生的事情; 你有一个函数(你的runIdentity)并提供一个使用的对象 - IIRC这是Python的功能def func(self).因此T,runIdentity实际上不是明确的类型,而是Identity<T>作为参数返回a T.

因此,它的类型Identity a -> a.

  • 如果你这样写,```runIdentity```的类型将是```Identity a - > Identity a - > a```.因为你来自OOP,所以想到这样:你调用一个成员函数```foo.bar()```,它返回类型```a```的东西.你认为函数```bar()```有类型```a```,但现在不是函数,不是吗?相反,它使用````foo```(为了方便起见,它是```Identity a```类型)来返回```a```.以C语言编写,例如,它是一个条形(Identity foo)```,它显然采用类型为```Identity```的参数:对象本身. (4认同)