这样的任何标准抽象? (又名猜猜结构)

时间:2015-01-09 19:52:13

标签: haskell

我在重构一个爱好项目时想出了以下结构。我想知道它是否匹配,或者可以调整以匹配一些现有的抽象/结构。我开始阅读ApplicativeFunctorArrow s,但无法建立连接,我没有更多想法。所以,最小的有用的例子:

-- trivial struct for this minimal example
data T = T { n :: Int, s :: String }

-- for any type `a`, there's exactly one way to update a `T`
class Gen a where
  gen :: a -> T -> T

-- helpers to compose `a`-s into a (T -> T)
(.>) :: (Gen a) => (T -> T) -> a -> (T -> T)
l .> x = l . (gen x)

(<.>) :: (Gen a, Gen b) => a -> b -> T -> T
l <.> r = (gen l) . (gen r)

-- For this example, let's say an Int is used to update a T by adding to its `n`
instance Gen Int where
  gen x t = t { n = (n t) + x }

-- and a Char is prepended to its `s`
instance Gen Char where
  gen c t = t { s = c : (s t) }

-- I can now express things like this easily
appendFooAndAdd3 = 'F' <.> 'o' .> 'o' .> (3::Int)

实际代码,以防更多上下文有用:https://github.com/abesto/hsircd/blob/cc8e9e33617f61ef9417b9476856a9fdc6bc4948/src/Server.hs#L81-L135

如果你发现一些可以在这里使用的结构,如果你能解释你是如何得出结论的,我将特别感激。我想我可以从中学到很多东西。

编辑:澄清我的问题:这可以通过使用一些现有的抽象来实现吗? ApplicativeFunctor是我的意思的例子,但它们似乎与这种情况不符。如果是的话,你是怎么来到这个结构的?

1 个答案:

答案 0 :(得分:4)

因此,我查看了lens的文档,以了解如何执行此操作。这似乎是惯用的方式:

{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
import Control.Lens.TH

data T = T
    { _n :: Int
    , _s :: String
    } deriving (Eq, Ord, Read, Show)

makeLenses ''T

appendFooAndAdd3 = (s <>~ "Foo") . (n +~ 3)

您会发现事情不是完全在您的方法中隐含的:在s <>~ "Foo"中,必须将字段s命名为操作{{1一个人想要表演,同样在<>。然而,这可能被视为一种优势,因为只有一种方法可以修改n +~ 3

在这种情况下,我认为Pythonism&#34; explicit比隐含&#34;更好。适用。