排名较高且不可预测的类型

时间:2012-01-05 08:47:16

标签: haskell higher-rank-types

我想实现以下stripPrefixBy函数:

-- psuedo code signature
stripPrefixBy :: forall a. [forall b. a -> Maybe b] -> [a] -> Maybe [a]
stripPrefixBy [] xs = Just xs
stripPrefixBy _ [] = Nothing
stripPrefixBy (p:ps) (x:xs) = case p x of
  Just _ -> stripPrefixBy ps xs
  Nothing -> Nothing

res :: Maybe String
res = stripPrefixBy [const (Just 0), Just] "abc"

wantThisToBeTrue :: Bool
wantThisToBeTrue = case res of
  Just "c" -> True
  _ -> False

我尝试过使用ImpredicativeTypesRankNTypes,但没有运气。如何以我希望的类型实现stripPrefixBy

2 个答案:

答案 0 :(得分:20)

签名的问题在于,传递给stripPrefixBy的列表被声明为一个函数列表,它将某个 a 作为参数,然后生成{{1}对于调用者选择的任何 b 。允许返回列表中的函数的唯一值是Maybe bNothing

也就是说,当使用impredicative polymorphism时,Just ⊥并不意味着它与存在量化类型相同:在那里,forall适用于<的类型em>构造函数,即

forall

但是在这里,它说该函数必须字面上是data MyType = forall a. Foo a Foo :: forall a. a -> MyType 类型。

以下是使用存在类型的更正示例:

forall b. a -> Maybe b

我相信UHC支持直接表达您想要的类型,

{-# LANGUAGE ExistentialQuantification #-}

data Pred a = forall b. Pred (a -> Maybe b)

stripPrefixBy :: [Pred a] -> [a] -> Maybe [a]
stripPrefixBy [] xs = Just xs
stripPrefixBy _ [] = Nothing
stripPrefixBy (Pred p:ps) (x:xs) = case p x of
  Just _ -> stripPrefixBy ps xs
  Nothing -> Nothing

res :: Maybe String
res = stripPrefixBy [Pred $ const (Just 0), Pred Just] "abc"

wantThisToBeTrue :: Bool
wantThisToBeTrue = case res of
  Just "c" -> True
  _ -> False

答案 1 :(得分:5)

另一个回答是,“你为什么要它拥有那种类型?”如果您很乐意将函数列表(stripPrefixBy的第一个参数)约束为具有相同的结果类型,则可以使用例如

res :: Maybe String
res = stripPrefixBy [const (Just undefined), Just] "abc"

然后给stripPrefixBy以下Haskell98类型:

stripPrefixBy :: [a -> Maybe b] -> [a] -> Maybe [a]

等效地,您可以观察到第一个参数中的函数结果无法使用(没有其他提及类型为“b”),因此您可能还有一个谓词列表:

stripPrefixBy :: [a -> Bool] -> [a] -> Maybe [a]
stripPrefixBy [] xs = Just xs
stripPrefixBy _ [] = Nothing
stripPrefixBy (p:ps) (x:xs) = case p x of
  True  -> stripPrefixBy ps xs
  False -> Nothing

res :: Maybe String
res = stripPrefixBy (map (isJust.) [const (Just undefined), Just]) "abc"

isJust :: Maybe a -> Bool
isJust (Just _) = True
isJust Nothing = False

但也许这个问题是你所拥有的更复杂问题的抽象,更简单的反应是行不通的?一切都应尽可能简单,但并不简单。