1

我对在 Haskell 中使用 foldl 的类型定义有疑问,我有以下类型:

data Client = GovOrg String
            | Company String Integer Person String
            | Individual Person Bool
            deriving Show

data Person = Person String String Gender
            deriving Show

data Gender = Male | Female | Unknown
  deriving (Show, Eq, Ord)

data GenderStat = GenderStat Gender Integer deriving Show

foldl 使用以下函数定义:

clientGender :: Client -> Gender
clientGender client = case client of
                          Company  _ _ (Person _ _ gender) _ -> gender
                          Individual (Person _ _ gender) _   -> gender
                          _                                  -> Unknown

incrementGenderStat :: GenderStat -> GenderStat
incrementGenderStat (GenderStat gender num) = GenderStat gender (num + 1)

genderStats:: [GenderStat] -> Client -> [GenderStat]
genderStats [maleStat, femaleStat, unknownStat] client = case clientGender client of
                                                           Male -> [incrementGenderStat maleStat, femaleStat, unknownStat]
                                                           Female -> [maleStat, incrementGenderStat femaleStat, unknownStat]
                                                           Unknown -> [maleStat, femaleStat, incrementGenderStat unknownStat]

-- genderStatsOfClients :: Client a -> 
genderStatsOfClients = foldl genderStats [GenderStat Male 0, GenderStat Female 0, GenderStat Unknown 0]

当我尝试将我的模块加载到ghci中时,它会引发错误:

  • Ambiguous type variable ‘t0’ arising from a use of ‘foldl’                                      │
      prevents the constraint ‘(Foldable t0)’ from being solved.                                      │
      Relevant bindings include                                                                       │
        genderStatsOfClients :: t0 Client -> [GenderStat]                                             │
          (bound at src/Section2/DataTypes.hs:82:1)                                                   │
      Probable fix: use a type annotation to specify what ‘t0’ should be.                             │
      These potential instances exist:                                                                │
        instance Foldable (Either a) -- Defined in ‘Data.Foldable’                                    │
        instance Foldable Maybe -- Defined in ‘Data.Foldable’                                         │                                                                
        instance Foldable ((,) a) -- Defined in ‘Data.Foldable’                                       │                                                                
        ...plus one other                                                                             │                                                                
        ...plus 22 instances involving out-of-scope types                                             │                                                                
        (use -fprint-potential-instances to see them all)                                             │                                                                
    • In the expression:                                                                              │
        foldl                                                                                         │
          genderStats                                                                                 │
          [GenderStat Male 0, GenderStat Female 0, GenderStat Unknown 0]                              │
      In an equation for ‘genderStatsOfClients’:                                                      │
          genderStatsOfClients                                                                        │
            = foldl                                                                                   │
                genderStats                                                                           │
                [GenderStat Male 0, GenderStat Female 0, GenderStat Unknown 0]                        │
Failed, modules loaded: none. 

我试图通过按照建议为函数提供类型注释来纠正这个问题:

-- genderStatsOfClients :: Foldable Client => ([GenderStat] -> a -> [GenderStat]) -> [GenderStat] -> [a] -> [GenderStat]

我想知道如何在这里提供适当的类型约束,如果我使用Foldable Client a,它表示它期望Foldable.

我也尝试过类型定义:

genderStatsOfClients :: (Foldable f, Client a) => ([GenderStat] -> (f a) -> [GenderStat]) -> [GenderStat] -> [(f a)] -> [GenderStat]
genderStatsOfClients = foldl genderStats [GenderStat Male 0, GenderStat Female 0, GenderStat Unknown 0]

引发错误:

src/Section2/DataTypes.hs:81:38: error:                                                               │
    • Expecting one fewer argument to ‘Client’                                                        │
      Expected kind ‘* -> Constraint’, but ‘Client’ has kind ‘*’                                      │
    • In the type signature:                                                                          │
        genderStatsOfClients :: (Foldable f, Client a) =>                                             │
                                ([GenderStat] -> (f a) -> [GenderStat])                               │
                                -> [GenderStat] -> [(f a)] -> [GenderStat]
4

1 回答 1

3

注释你的定义genderStatsOfClients告诉编译器你的可折叠是一个列表:

genderStatsOfClients :: [Client] -> [GenderStat]
于 2017-05-30T20:38:58.457 回答