简化代码(需要帮助来完善此问题的标题...)

时间:2019-02-10 10:33:23

标签: haskell

我没有我要找的名字...(我将立即更新此问题的标题...)。

这里是上下文:

data EventStoreMicroService = EventStoreMicroService {
                                    urlHost :: String,
                                    port :: Int,
                                    username :: ByteString,
                                    password :: ByteString}

getCredentials :: EventStoreMicroService -> EventStore.Credentials
getCredentials EventStoreMicroService {username,password} = EventStore.credentials username password

getConnectionType :: EventStoreMicroService -> EventStore.ConnectionType
getConnectionType EventStoreMicroService {urlHost,port} = (EventStore.Static urlHost port)

getEventStoreSettings :: EventStoreMicroService -> EventStore.Settings
getEventStoreSettings service = EventStore.defaultSettings

我具有此功能:

connect :: Settings -> ConnectionType -> IO Connection

这是我到目前为止所做的:

let microservice = EventStoreMicroService {
      urlHost = "127.3.4.5",
      port = 2000,
      username = "xxxx",
      password = "yyy"}
    eventStoreSettings = getEventStoreSettings microservice
    eventStoreConnectionType = getConnectionType microservice

connect eventStoreSettings eventStoreConnectionType

我正在寻找一个神奇的函数(我将其命名为“ from”),该函数将能够以这种方式表达它:

let microservice = EventStoreMicroService {
      urlHost = "127.3.4.5",
      port = 2000,
      username = "xxxx",
      password = "yyy"}
    eventStoreSettings = getEventStoreSettings microservice
    eventStoreConnectionType = getConnectionType microservice

connect $ from microservice getEventStoreSettings getConnectionType

它基本上将2个函数应用于数据类型,该数据类型返回让说(a,b)并将该元组提供给函数connect ...

2 个答案:

答案 0 :(得分:3)

所以我认为您正在追求这样的事情?

from :: a -> (a -> b) -> (a -> b) -> (b, b)
from a f g = (f a, g a)

然后您可以像这样使用它:

uncurry connect $ from microservice getEventStoreSettings getConnectionType

我确定标准库中可能存在类似from的内容,但是在Hoogle上进行快速搜索后找不到任何内容。

编辑:正如@WillNess在评论中指出的那样,可以通过几种方式对此进行改进。

首先,我上面的from版本可以简化为from a f g = (f &&& g) a

第二,您可以通过定义更通用的uncurry版本来避免使用from

from' :: (b -> b -> c) -> a -> (a -> b) -> (a -> b) -> c
from' c a f g = c (f a) (g a)

允许一个人简单地做:

from' connect  microservice getEventStoreSettings getConnectionType

答案 1 :(得分:2)

请注意,您实际上并不需要魔术功能。仅将现有的Applicative实例用于函数可能会更清楚。

data EventStoreMicroService = EventStoreMicroService {
                                urlHost :: String,
                                port :: Int,
                                username :: ByteString,
                                password :: ByteString}

getCredentials :: EventStoreMicroService -> EventStore.Credentials
getCredentials = EventStore.Credentials <$> username <*> password

getConnectionType :: EventStoreMicroService -> EventStore.ConnectionType
getConnectionType = EventStore.Static <$> urlHost <*> port

getEventStoreSettings :: EventStoreMicroService -> EventStore.Settings
getEventStoreSettings _ = EventStore.defaultSettings
-- or getEventStoreSettings = const EventStore.defaultSettings

然后

let microservice = EventStoreMicroService { urlHost = "127.3.4.5"
                                          , port = 2000
                                          , username = "xxxx"
                                          , password = "yyy"
                                          }    
(connect <$> getEventStoreSettings <*> getConnectionType) microservice
-- or skip getEventStoreSettings, and use defaultSettings directly
-- connect EventStore.defaultSettings (getConnectionType microservice)