假设我们有以下数据类型
data GsdCommand = CreateWorkspace { commandId :: CommandId , workspaceId ::WorkspaceId , workspaceName :: Text }
| RenameWorkspace { commandId :: CommandId , workspaceId ::WorkspaceId , workspaceNewName :: Text }我想要有一个只接受CreateWorkspace的函数:
{-# LANGUAGE DataKinds #-}
handle :: Offset ->
`CreateWorkspace CommandId WorkspaceId Text ->
IO (CommandHandlingResult)这是我自然而然的做法,但我有以下编译器错误:
Expected a type, but‘ 'CreateWorkspace CommandId WorkspaceId Text’ has kind ‘GsdCommand’
Expected kind ‘CommandId’, but ‘CommandId’ has kind ‘*’
Expected kind ‘WorkspaceId’, but ‘WorkspaceId’ has kind ‘*’
Expected kind ‘Text’, but ‘Text’ has kind ‘*’这是上下文:
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE NamedFieldPuns #-}
module Eventuria.GSD.Write.CommandConsumer.Handling.HandleGSDCommand (handleGSDCommand) where
import Eventuria.Libraries.PersistedStreamEngine.Interface.PersistedItem
import Eventuria.Libraries.CQRS.Write.CommandConsumption.Definitions
import Eventuria.Libraries.CQRS.Write.CommandConsumption.CommandHandlingResult
import Eventuria.GSD.Write.Model.WriteModel
import Eventuria.GSD.Write.Model.Commands.Command
import Eventuria.GSD.Write.CommandConsumer.Handling.CommandPredicates
import qualified Eventuria.GSD.Write.CommandConsumer.Handling.Commands.CreateWorkspace as CreateWorkspace
import qualified Eventuria.GSD.Write.CommandConsumer.Handling.Commands.RenameWorkspace as RenameWorkspace
import qualified Eventuria.GSD.Write.CommandConsumer.Handling.Commands.SetGoal as SetGoal
import qualified Eventuria.GSD.Write.CommandConsumer.Handling.Commands.RefineGoalDescription as RefineGoalDescription
import qualified Eventuria.GSD.Write.CommandConsumer.Handling.Commands.StartWorkingOnGoal as StartWorkingOnGoal
import qualified Eventuria.GSD.Write.CommandConsumer.Handling.Commands.PauseWorkingOnGoal as PauseWorkingOnGoal
import qualified Eventuria.GSD.Write.CommandConsumer.Handling.Commands.NotifyGoalAccomplishment as NotifyGoalAccomplishment
import qualified Eventuria.GSD.Write.CommandConsumer.Handling.Commands.GiveUpOnGoal as GiveUpOnGoal
import qualified Eventuria.GSD.Write.CommandConsumer.Handling.Commands.ActionizeOnGoal as ActionizeOnGoal
import qualified Eventuria.GSD.Write.CommandConsumer.Handling.Commands.NotifyActionCompleted as NotifyActionCompleted
type GSDCommandHandler = Maybe GsdWriteModel ->
(Persisted GsdCommand) ->
IO (CommandHandlingResult)
handleGSDCommand :: HandleCommand GsdWriteModel
handleGSDCommand writeModelMaybe
PersistedItem {offset , item = command }
| (isFirstCommand offset) && (not . isCreateWorkspaceCommand) command = return $ CommandRejected "CreateWorkspace should be the first command"
| otherwise = gsdCommandHandler writeModelMaybe PersistedItem {offset , item = (fromCommand command) }
gsdCommandHandler :: GSDCommandHandler
gsdCommandHandler
writeModelMaybe
PersistedItem {offset , item = gsdCommand } =
case (writeModelMaybe, gsdCommand) of
(Nothing ,CreateWorkspace {commandId, workspaceId, workspaceName}) -> CreateWorkspace.handle offset commandId workspaceId workspaceName
(Just writeModel,RenameWorkspace {commandId, workspaceId, workspaceNewName}) -> RenameWorkspace.handle offset writeModel commandId workspaceId workspaceNewName
(Just writeModel,SetGoal {commandId, workspaceId, goalId, goalDescription}) -> SetGoal.handle offset writeModel commandId workspaceId goalId goalDescription
(Just writeModel,RefineGoalDescription {commandId, workspaceId, goalId, refinedGoalDescription}) -> RefineGoalDescription.handle offset writeModel commandId workspaceId goalId refinedGoalDescription
(Just writeModel,StartWorkingOnGoal {commandId, workspaceId, goalId}) -> StartWorkingOnGoal.handle offset writeModel commandId workspaceId goalId
(Just writeModel,PauseWorkingOnGoal {commandId, workspaceId, goalId}) -> PauseWorkingOnGoal.handle offset writeModel commandId workspaceId goalId
(Just writeModel,NotifyGoalAccomplishment {commandId, workspaceId, goalId}) -> NotifyGoalAccomplishment.handle offset writeModel commandId workspaceId goalId
(Just writeModel,GiveUpOnGoal {commandId, workspaceId, goalId, reason}) -> GiveUpOnGoal.handle offset writeModel commandId workspaceId goalId reason
(Just writeModel,ActionizeOnGoal {commandId, workspaceId, goalId, actionId, actionDetails}) -> ActionizeOnGoal.handle offset writeModel commandId workspaceId goalId actionId actionDetails
(Just writeModel,NotifyActionCompleted {commandId, workspaceId, goalId, actionId}) -> NotifyActionCompleted.handle offset writeModel commandId workspaceId goalId actionId
(_ ,_) -> return $ CommandRejected "Scenario not handle"我必须对字段进行模式匹配,并将它们传递给句柄....
发布于 2019-05-03 01:45:14
DataKinds创建新的种类和值,但不更改值的类型。CreateWorkspace值的类型仍然是GsdCommand,而不是'CreateWorkspace。
一种选择是使用幻影类型,它不需要DataKinds扩展。
data CreateWorkspace
data RenameWorkspace
data GsdCommand t = GsdCommand CommandID WorkspaceID Text
handle :: Offset -> GsdCommand CreateWorkspace -> IO CommandHandlingResult
handle o (GsdCommand cmdID wkspID wkspName) = ...发布于 2019-05-03 16:23:25
我已经在问题本身中添加了解决方案,但基本上我必须传递基于类的方式来表达问题,而不是使用基于替换的方法(使用Sum类型...)试着推广价值观。
https://stackoverflow.com/questions/55956320
复制相似问题