gpt4 book ai didi

haskell - 类型 家庭 类型 黑客

转载 作者:行者123 更新时间:2023-12-02 15:40:53 25 4
gpt4 key购买 nike

我正在尝试编写一个相当多态的库。我遇到了一种更容易表现出来却很难说出来的情况。它看起来有点像这样:

{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
import Data.Map (Map)
import qualified Data.Map as Map

class Format f where type Target f
class Format f => Formatter x f where
target :: forall y. Formatable y => Target f -> x -> y
class Formatable y where name :: y -> String

instance Formatable Integer where name = show
instance Formatable Int where name = show

split :: forall x f. (Format f, Formatter x f) => x -> f -> String -> [Either String (Target f)]
split = undefined

display :: forall x f. (Format f, Formatter x f) => f -> String -> x -> String
display f str x = let
chunks = split x f str
built = foldr apply "" chunks
apply (Left s) accum = accum ++ s
apply (Right t) accum = accum ++ name (target t x)
in foldr apply "" chunks

本质上,我们有多态的Format,它定义了许多Target。还有许多 Formattable 对象,它们知道如何响应一堆不同的格式选项(这里简化为 name)。

这些格式表以多种方式组成,并且可以响应许多不同的目标。 Formatter 本质上是 FormatFormattable 之间的路由器——给定目标(来自特定格式),它们会用合适的 进行响应可格式化对象。

这一切都非常抽象。这是一个例子:

  • DateFormat 指定诸如 YearMonthDay 之类的目标。
  • MonthTypeIntFormattable 新类型,其名称例如“February”
  • 还有一个简单的实例Formattable Int where name = show
  • DateTime 可能是 (Int, MonthType, Int) 的类型同义词。

(显然,我在这里删除了很多机制,例如通过管道传递正确的值,但您明白了。)

display 函数相当简单。它需要一个格式化程序、一个指定格式的字符串、一个要显示的对象,并将其全部呈现为一个字符串。

首先,它将字符串分解为目标和字符串。例如,日期格式化程序可能会将字符串 "%Y-%m-%d" 分解为 [Right Year, Left "-", Right Month, Left "-", Right Day ]split 函数执行此操作,并已在此处进行编辑。

display 函数只是跟踪每个目标的Formattable 并累积字符串。

或者,至少,应该是这样。

但是类型检查失败并出现以下错误:

Reduced.hs:20:16:
Could not deduce (Target f ~ Target f0)
from the context (Format f, Formatter x f)
bound by the type signature for
display :: (Format f, Formatter x f) => f -> String -> x -> String
at Reduced.hs:(19,5)-(24,30)
NB: `Target' is a type function, and may not be injective
Expected type: [Either [Char] (Target f0)]
Actual type: [Either String (Target f)]
In the return type of a call of `split'
In the expression: split x f str
In an equation for `chunks': chunks = split x f str
Failed, modules loaded: none.

我一生都无法弄清楚为什么。我做错了什么?

最佳答案

问题在于目标f无法确定f,这意味着该函数

target :: (Formatter f x, Formatable y) => Target f -> x -> y

永远无法被调用。无论您为 target 提供什么类型注释,您都无法确定 f 是什么,因此编译器永远无法确定哪个 Formatter > 要使用的实例。我不是 100% 确定,但解决方案可能不是使用多参数类型类,而是让 x 或 f 之一成为另一个的函数。另外,您可能应该完全删除 Format 类(您知道不需要类来使用类型系列吗?)。也许是这样的:

class Formatter x where
type Format x
target :: Formatable y => Format x -> x -> y

关于haskell - 类型 家庭 类型 黑客,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10059557/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com