Haskell 可能实例化或不实例化TypeClass的函数参数?
这就是我想让我的处理者看起来的样子-Haskell 可能实例化或不实例化TypeClass的函数参数?,haskell,yesod,Haskell,Yesod,这就是我想让我的处理者看起来的样子- getUserStudentsR :: UserId -> Handler TypedContent getUserStudentsR userId = getStudentEntitiesForCoach userId >>= returnTypedContent . map toUserStudentResponse 其中,Student是一个持久的实体(细节大多不重要),并且 及 现在很明显,除非Use
getUserStudentsR :: UserId -> Handler TypedContent
getUserStudentsR userId =
getStudentEntitiesForCoach userId
>>= returnTypedContent . map toUserStudentResponse
其中,Student是一个持久的实体(细节大多不重要),并且
及
现在很明显,除非UserStudentResponse实例化ToJSON并提供ToJSON的实现,否则这不会编译。但是,我想让returnTypedContent函数成为通用函数-类似于-
returnTypedContent x = selectRep $ do
-- if ToJSON x --
provideJSON x
-- if ToHTML x -- -- note this is not an either or
provideRep $ return $ toHtml $ a
我想这样做,以便可以扩展returnTypedContent以提供各种ContentType的返回,然后根据处理程序中使用的数据类型是否实例化某些类型的类(例如ToJSON),我们提供了不同的内容
在不进入模板Haskell的情况下,这样做可能吗?您可以使用这样的方法(启用GADTs): 然后您可以进行模式匹配:
returnTypedContent (Json x) = selectRep (provideJSON x)
returnTypedContent (Html x) = selectRep (provideRep $ return $ toHtml x)
您必须显式地包装数据,但这不会有太大问题。您可以使用类似的方法(启用GADT): 然后您可以进行模式匹配:
returnTypedContent (Json x) = selectRep (provideJSON x)
returnTypedContent (Html x) = selectRep (provideRep $ return $ toHtml x)
您必须显式地包装数据,但这不会有太大问题。您不能这样做。GHC目前没有提供“在实例头上匹配”的方法 所以这是不可能的
instance Foo a => Bar a where ...
instance Bar a where ...
如果Foo匹配,调度将在两者之间进行选择
但是,对于闭合类型族,可以在特定实例中给出错误提示。GHC手册演示了这项技术:您不能这样做。GHC目前没有提供“在实例头上匹配”的方法 所以这是不可能的
instance Foo a => Bar a where ...
instance Bar a where ...
如果Foo匹配,调度将在两者之间进行选择
但是,对于闭合类型族,可以在特定实例中给出错误提示。GHC手册演示了这项技术:我不是一个真正的YesSOD用户,但是
selectRep
做什么?仅仅为UserStudentResponse
创建一个ToTypedContent
实例就足够了吗?你不能直接这样做(以其他人想出一些聪明的把戏的机会为代价);像ToJSON[a]
这样的约束是命题,而不是语言内部的布尔值。尝试写下returnTypedContent
的类型。这将有助于了解您为什么不能这样做,并可能有助于设计一个变通方法(尽管我现在不知道它是什么样子)。使用-XOverlappingInstances
,您可以创建ToJSON
和ToHTML
的“回退”实例。您可能能够专门处理从回退实例中获得的值(如果没有通常禁止使用的json/html值,它们可能是抛出一些异常值
)。我认为最好使用模板haskell编写大量实例。@aavogt-我将尝试回退实例。现在需要阅读它们。同意,template haskell可能是实现这一目标的唯一方法,但如果可以,我想避免它。我不是一个真正的YesSOD用户,但是selectRep
做什么呢?仅仅为UserStudentResponse
创建一个ToTypedContent
实例就足够了吗?你不能直接这样做(以其他人想出一些聪明的把戏的机会为代价);像ToJSON[a]
这样的约束是命题,而不是语言内部的布尔值。尝试写下returnTypedContent
的类型。这将有助于了解您为什么不能这样做,并可能有助于设计一个变通方法(尽管我现在不知道它是什么样子)。使用-XOverlappingInstances
,您可以创建ToJSON
和ToHTML
的“回退”实例。您可能能够专门处理从回退实例中获得的值(如果没有通常禁止使用的json/html值,它们可能是抛出一些异常值
)。我认为最好使用模板haskell编写大量实例。@aavogt-我将尝试回退实例。现在需要阅读它们。同意,模板haskell可能是实现这一目标的唯一方法,但如果可以,我想避免它。不。。这不是一个“如果”的问题。。如果一个实例同时实例化了ToJSON和ToHTML,我的代码需要同时执行(provideJSON和provideRep),也就是说,YesSOD可以选择响应这两种类型的内容类型请求。。按照您的方式,如果有一个实例化ToJSON的实例,它将永远不会执行provideRep。也。。我无法发送不实现ToJSON或ToHTML的“a”。顺便说一句,@RoopeshShenoy:您当然可以扩展包装器,使其同时包含和构造函数。(您最好使用@aavogt的OverlappingInstances
建议。但是我会为selectRep创建一个单独的类型类,并在那里使用重叠,而不是ToJSON
和ToHTML
)有趣的建议,让我看看是否有类似的事情works@RoopeshShenoy:我一直在玩弄重叠实例
有一段时间了,我不确定我的建议是否有效。不。。这不是一个“如果”的问题。。如果一个实例同时实例化了ToJSON和ToHTML,我的代码需要同时执行(provideJSON和provideRep),也就是说,YesSOD可以选择响应这两种类型的内容类型请求。。按照您的方式,如果有一个实例化ToJSON的实例,它将永远不会执行provideRep。也。。我无法发送不实现ToJSON或ToHTML的“a”。顺便说一句,@RoopeshShenoy:您当然可以扩展包装器,使其同时包含和构造函数。(您最好使用@aavogt的OverlappingInstances
建议。但是我会为selectRep创建一个单独的类型类,并在那里使用重叠而不是ToJSON
和ToHTML
)有趣的建议,让我看看是否有类似的东西works@RoopeshSheno
instance Foo a => Bar a where ...
instance Bar a where ...