定义可观数据记录的高阶函数



我假装创建一个高阶函数,该功能用作其参数之一,属于某个数据类型的记录。

例如:

type Debt = Float
type Power = Int
Data State = S String Debt 
Data City = C String Power Debt
Data Country = Country
   { states :: [State]
   , cities :: [City] }
upDetail :: (Country -> [a]) 
         -> ([a] -> b -> [a])
         -> b -> Country -> Country
upDetail f g b country = country { f = new }
         where old = f country
               new = g old b

上面的功能应该做的是选择国家记录的元素(具有函数类型Country -> [a]),并根据某个功能类型[a] -> b -> [a]和某个b

对其进行更改

但是,当我尝试编译时,我会发现一个错误说:

" f"不是(可见的)构造函数字段名称

有什么办法可以克服这个问题?我想到使用也许是我的结果,但我不知道该怎么做。

正如评论所述,对此的正常解决方案是使用镜头:

upDetail :: Lens Country [a]
         -> ([a] -> b -> [a])
         -> b -> Country -> Country
upDetail f g b country = set f country new
         where old = get f country
               new = g old b

但是,镜头并不难处理,尤其是为了简单的目的。

表达镜头的最简单方法是作为getter和setter函数:

data Lens s a = Lens
  { get :: s -> a
  , set :: s -> a -> s
  }
_states :: Lens Country [State]
_states = Lens states $ c new -> c { states = new }
_cities :: Lens Country [City]
_cities = Lens cities $ c new -> c { cities = new }

这使我们可以轻松地修改一个国家的城市或状态:

λ Country [] []
Country {states = [], cities = []}
λ upDetail _cities (cs c -> c:cs) (C "Hereford" 100 3000) it                                                        
Country {states = [], cities = [C "Hereford" 100 3000.0]}
λ upDetail _states (cs c -> c:cs) (S "Delmarva" 4) it                                                        
Country {states = [S "Delmarva" 4.0], cities = [C "Hereford" 100 3000.0]}

一旦您开始考虑编写镜头,镜头就会变得更加复杂,但您可以进入这里,但您可以。

最新更新