假设我们具有以下数据类型
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"
我必须对字段进行模式匹配并将其传递给句柄。...
答案 0 :(得分:2)
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) = ...
答案 1 :(得分:0)
我已经在问题本身中添加了解决方案,但基本上我必须传递基于类的表达问题的方式,而不是使用基于交替的方式(使用Sum Types ...)并尝试使用促进价值...