gpt4 book ai didi

functional-programming - Eff monad 要求与 Debug.Trace.Trace 一起排

转载 作者:行者123 更新时间:2023-12-04 19:05:57 30 4
gpt4 key购买 nike

我正在将 History.js 中的绑定(bind)编写到 PureScript 中,但仍在努力理解 Eff monad、一排效果是什么以及它们为何有值(value)。现在我用 EasyFFI 写了以下内容

type Title        = String
type Url = String
type State = forall a. {title :: Title, url :: Url | a}
type Data = forall a. { | a}
type StateUpdater = Data -> Title -> Url -> Unit

-- this function is a work around for 'data' as a reserved word.
foreign import getData
"function getData(state){ return state['data']; }"
:: forall a b. { | a} -> b

unwrapState :: StateUpdater -> State -> Unit
unwrapState f s = f (getData s) s.title s.url

replaceState' :: StateUpdater
replaceState' = unsafeForeignProcedure ["data","title","url"] "History.replaceState(data,title,url)"
replaceState :: State -> Unit
replaceState = unwrapState replaceState'

foreign import data BeforeEach :: !
beforeEach :: forall e a. Eff e a -> Eff (beforeEach :: BeforeEach | e) Unit
beforeEach = unsafeForeignProcedure ["fn",""] "window.beforeEach(fn);"

稍后在代码中我有以下内容:
beforeEach $ do 
replaceState {title = "wowzers!", url = "/foos"}

并得到以下错误
 Cannot unify Prelude.Unit with Control.Monad.Eff.Eff u2518 u2517.

我尝试以各种方式操纵类型签名以尝试使其全部对齐,但我真的不明白出了什么问题。所以它只是在这一点上猜测。

最佳答案

我对您的代码的修改版本在这篇文章的末尾,但我必须进行一些修改才能使其编译:

我认为目的是为了您的StateUpdater为了对浏览器历史产生影响,所以我将其类型更改为使用 Eff带有新的 History 的 monad效果类型。这是主要问题,因为您的最后一行使用了 replaceState其结果类型不在 Eff 中单子(monad)。这导致了您看到的类型错误。

我将类型同义词中的一些普遍量化的类型变量移到了函数类型中。我还删除了您的 Data输入同义词并将数据内容移动到新的 data State 中的字段类型。

这很重要,因为您之前的 Data类型没有居民。有一个普遍的误解(原因我不明白)forall a. { | a}是一种“我不关心字段”的记录。这是不正确的 - 这种类型表示包含所有可能存在的字段的记录类型,并且这种类型显然是无人居住的。 forall a. {| a} -> r 之间有一个重要区别。和 (forall a. {| a}) -> r从调用者的角度来看。

回答您最初的问题:“什么是一排效果,它们为什么有用?” - 行最初被添加到 PureScript 以处理记录类型的多态性,而不必求助于子类型。行允许我们为使用记录的函数赋予多态类型,这样我们就可以将“记录的其余部分”捕获为类型系统中的一个概念。

在处理效果时,行也被证明是一个有用的概念。就像我们不关心记录的其余部分是什么一样,我们通常也不关心一组效果的其余部分是什么样的,只要所有效果在类型系统中正确传播即可。

举个例子,我修改后的代码有两个效果:History ,以及您的 BeforeEach .行动beforeEachreplaceState每个都只使用这些效果之一,但它们的返回类型是多态的。这允许在 main 中组合这两个函数。具有两种效果,并正确键入。 main有类型 forall eff. Eff (history :: History, beforeEach :: BeforeEach | eff) {}这是最通用的类​​型,由类型检查器推断。

简而言之,效果系统中的行提供了一种巧妙的方式来处理各种“原生”效果的交错,因此开发人员不必担心效果的顺序或 lift 之类的事情。 ing 计算 à la mtl .

module Main where

import EasyFFI
import Control.Monad.Eff

type Title = String
type Url = String
type State d = { title :: Title, url :: Url, "data" :: { | d } }

type StateUpdater d = forall eff. { | d } -> Title -> Url -> Eff (history :: History | eff) {}

foreign import data History :: !

unwrapState :: forall eff d. StateUpdater d -> State d -> Eff (history :: History | eff) {}
unwrapState f s = f s."data" s.title s.url

replaceState' :: forall d. StateUpdater d
replaceState' = unsafeForeignProcedure ["d","title","url"] "History.replaceState(d,title,url)"

replaceState :: forall eff d. State d -> Eff (history :: History | eff) {}
replaceState = unwrapState replaceState'

foreign import data BeforeEach :: !

beforeEach :: forall e a. Eff e a -> Eff (beforeEach :: BeforeEach | e) {}
beforeEach = unsafeForeignProcedure ["fn",""] "window.beforeEach(fn);"

main = beforeEach $ do
replaceState { title: "wowzers!", url: "/foos", "data": {} }

关于functional-programming - Eff monad 要求与 Debug.Trace.Trace 一起排,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24782835/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com