如何直接通过其类型构造函数在 Purescript 中创建 Effect?
How do you create an Effect in Purescript directly via its type constructor?
是否可以直接使用Effect
构造函数?例如foo = Effect "howdy!"
看来这样应该是可以的。它似乎是一个类型构造函数。
:kind Effect
Type -> Type
但是,如果我尝试构造它,则会抛出错误
Effect 1234
Unknown data constructor Effect
我只能创建一个 'indirectly' 和 pure
myeffect :: Effect Int
myeffect = pure 123
我错过了什么吗?
这不是类型的工作方式
签名 Effect :: Type -> Type
意味着如果你使用单词 Effect
并在其右侧附加一个类型,则其结果将是另一种类型。所以:
Effect :: Type -> Type
Int :: Type
Effect Int :: Type
这并没有说明创建类型为 Effect
的 值 。即:
Effect Int :: Type
x :: Effect Int
x = Effect 42 -- not necessarily allowed
对于许多类型,这恰好工作得很好,例如:
Maybe Int :: Type
x :: Maybe Int
x = Just 42 -- perfectly valid
但不必如此。这完全取决于类型的定义方式。例如:
data MyType a = Foo
MyType :: Type -> Type
MyType Int :: Type
x = Foo 42 -- now allowed
y = Foo -- allowed
请注意,我使用单词 Foo
来构造 MyType
的值,而不是单词 MyType
。这是因为它们是不同的东西。 MyType
是类型的名称,Foo
是 构造函数的名称 - 这是一个可以构造(因此得名)值的函数类型。 构造函数的其他示例是Just
和Nothing
——它们都用于构造Maybe
.
类型的值
构造函数可以具有与类型本身相同数量的参数,也可以具有更少或更多的参数。例如:
data Type1 a = Ctor1 a
data Type2 a = Ctor2
data Type3 a = Ctor3 a a
x :: Type1 Int
x = Ctor1 42
y :: Type2 Int
y = Ctor2
z :: Type3 Int
z = Ctor3 42 84
因此,总结一下:根据类型的定义方式,您可以使用也可以不使用类型的名称来创建该类型的值,就像您尝试使用 Effect
.
(另外,某些类型可能有 多个 构造函数,例如 data Maybe a = Just a | Nothing
,但这已经花费了太长时间)
但所有这些甚至不适用于 Effect
,因为...
这不是 Effect
的工作方式
Effect
根本没有任何构造函数。无论参数如何,都绝对没有办法直接创建这种类型的值。
这是因为Effect
是魔法。类型 Effect Int
的值肯定是 NOT 一种 "box" ,其中包含 Int
。 No-no-no.
相反,类型 Effect Int
的值是一个 程序 ,它在执行时最终会产生一个 Int
。你不能看里面,你不能把它拆开,你唯一能做的就是执行它。
你是如何执行的?简单!你 return 它来自你的 main
函数!
不,说真的,这是执行 Effect
的唯一方法。 (嗯,好吧,还有 unsafePerformEffect
,然后你可以用 FFI 来做,但那些是入门的 hack,不要去那里)
您执行效果的正常方式是 return 如果来自您的 main
函数,运行时将处理它。轰!
另一种看待它的方式是你的整个程序很大(或很小)Effect
。那是你的程序。
你可以用效果做的另一件事是使用运算符>>=
(或其邪恶的双胞胎=<<
)将它与另一个效果结合起来。例如:
x = pure 40
y = x >>= \a -> a + 2
z = pure 42
这里,y
和 z
是等效的程序:两者在执行时都会产生数字 42
.
这就是您在 PureScript 中编写程序的方式:您从 built-in ("magic") 产生效果的函数开始,例如 cwd
或 readLine
或不管怎样,然后通过 >>=
或 =<<
或 do
符号(这是 >>=
的语法糖)将这些效果与其他效果组合在一起。然后,由许多小效果构成的大效果,您从 main
函数 return - 瞧,您得到了一个程序!
是否可以直接使用Effect
构造函数?例如foo = Effect "howdy!"
看来这样应该是可以的。它似乎是一个类型构造函数。
:kind Effect
Type -> Type
但是,如果我尝试构造它,则会抛出错误
Effect 1234
Unknown data constructor Effect
我只能创建一个 'indirectly' 和 pure
myeffect :: Effect Int
myeffect = pure 123
我错过了什么吗?
这不是类型的工作方式
签名 Effect :: Type -> Type
意味着如果你使用单词 Effect
并在其右侧附加一个类型,则其结果将是另一种类型。所以:
Effect :: Type -> Type
Int :: Type
Effect Int :: Type
这并没有说明创建类型为 Effect
的 值 。即:
Effect Int :: Type
x :: Effect Int
x = Effect 42 -- not necessarily allowed
对于许多类型,这恰好工作得很好,例如:
Maybe Int :: Type
x :: Maybe Int
x = Just 42 -- perfectly valid
但不必如此。这完全取决于类型的定义方式。例如:
data MyType a = Foo
MyType :: Type -> Type
MyType Int :: Type
x = Foo 42 -- now allowed
y = Foo -- allowed
请注意,我使用单词 Foo
来构造 MyType
的值,而不是单词 MyType
。这是因为它们是不同的东西。 MyType
是类型的名称,Foo
是 构造函数的名称 - 这是一个可以构造(因此得名)值的函数类型。 构造函数的其他示例是Just
和Nothing
——它们都用于构造Maybe
.
构造函数可以具有与类型本身相同数量的参数,也可以具有更少或更多的参数。例如:
data Type1 a = Ctor1 a
data Type2 a = Ctor2
data Type3 a = Ctor3 a a
x :: Type1 Int
x = Ctor1 42
y :: Type2 Int
y = Ctor2
z :: Type3 Int
z = Ctor3 42 84
因此,总结一下:根据类型的定义方式,您可以使用也可以不使用类型的名称来创建该类型的值,就像您尝试使用 Effect
.
(另外,某些类型可能有 多个 构造函数,例如 data Maybe a = Just a | Nothing
,但这已经花费了太长时间)
但所有这些甚至不适用于 Effect
,因为...
这不是 Effect
的工作方式
Effect
根本没有任何构造函数。无论参数如何,都绝对没有办法直接创建这种类型的值。
这是因为Effect
是魔法。类型 Effect Int
的值肯定是 NOT 一种 "box" ,其中包含 Int
。 No-no-no.
相反,类型 Effect Int
的值是一个 程序 ,它在执行时最终会产生一个 Int
。你不能看里面,你不能把它拆开,你唯一能做的就是执行它。
你是如何执行的?简单!你 return 它来自你的 main
函数!
不,说真的,这是执行 Effect
的唯一方法。 (嗯,好吧,还有 unsafePerformEffect
,然后你可以用 FFI 来做,但那些是入门的 hack,不要去那里)
您执行效果的正常方式是 return 如果来自您的 main
函数,运行时将处理它。轰!
另一种看待它的方式是你的整个程序很大(或很小)Effect
。那是你的程序。
你可以用效果做的另一件事是使用运算符>>=
(或其邪恶的双胞胎=<<
)将它与另一个效果结合起来。例如:
x = pure 40
y = x >>= \a -> a + 2
z = pure 42
这里,y
和 z
是等效的程序:两者在执行时都会产生数字 42
.
这就是您在 PureScript 中编写程序的方式:您从 built-in ("magic") 产生效果的函数开始,例如 cwd
或 readLine
或不管怎样,然后通过 >>=
或 =<<
或 do
符号(这是 >>=
的语法糖)将这些效果与其他效果组合在一起。然后,由许多小效果构成的大效果,您从 main
函数 return - 瞧,您得到了一个程序!