有这样的标准抽象吗? (又名。猜猜结构)
Any standard abstraction like this? (aka. Guess The Structure)
我在重构一个业余项目时想到了以下结构。我想知道它是否匹配或可以调整以匹配某些现有的抽象/结构。我开始阅读 Applicative
、Functor
和 Arrow
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
如果您找到可以在这里使用的结构,请解释您是如何得出结论的,我将不胜感激。我想我可以从中学到很多东西。
编辑:澄清我的问题:这可以通过使用一些现有的抽象来实现吗? Applicative
和 Functor
是我的意思的例子,但他们似乎不符合这种情况。如果有,你是怎么得到这个结构的?
因此,我查看了 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
和操作<>
一个人要表演,n +~ 3
也一样。然而,这可能被视为一种优势,因为很少有只有一种方法可以修改 T
.
在这种情况下,我认为 Pythonism "explicit is better than implicit" 适用。
我在重构一个业余项目时想到了以下结构。我想知道它是否匹配或可以调整以匹配某些现有的抽象/结构。我开始阅读 Applicative
、Functor
和 Arrow
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
如果您找到可以在这里使用的结构,请解释您是如何得出结论的,我将不胜感激。我想我可以从中学到很多东西。
编辑:澄清我的问题:这可以通过使用一些现有的抽象来实现吗? Applicative
和 Functor
是我的意思的例子,但他们似乎不符合这种情况。如果有,你是怎么得到这个结构的?
因此,我查看了 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
和操作<>
一个人要表演,n +~ 3
也一样。然而,这可能被视为一种优势,因为很少有只有一种方法可以修改 T
.
在这种情况下,我认为 Pythonism "explicit is better than implicit" 适用。