计算List haskell中的编辑操作成本

时间:2018-10-23 16:36:01

标签: haskell

data Edit = 
        Change Char Char|
        Copy Char|
        Delete Char|
        Insert Char
        deriving (Eq, Show)

cost :: [Edit] -> Int
cost edits
    = length ( filter (\x -> x /= Copy) edits )

main :: IO()
main
    = putStrLn ( show ( cost [Copy 'e', Copy 'x', Insert 'm', Insert 'o', Change 'e' 'u', Copy 't', Delete 'e', Change 'r' 'h'] ) )

我正在尝试使用代数数据类型来计算List的成本,每次编辑的成本为1,副本的成本为0。

我当前收到错误消息:

    * Couldn't match type `Edit' with `Char -> Edit'
      Expected type: [Char -> Edit]
        Actual type: [Edit]
    * In the second argument of `filter', namely `edits'
      In the first argument of `length', namely
        `(filter (\ x -> x /= Copy) edits)'
      In the expression: length (filter (\ x -> x /= Copy) edits)
                                        ^^^^^

我看不到掌握代数类型,因此不胜感激

1 个答案:

答案 0 :(得分:1)

CopyEdit的构造函数,其一个字段类型为Char,因此具有以下函数类型:

Copy :: Char -> Edit

实际上,使用{-# LANGUAGE GADTSyntax #-}可以在定义中显式地编写每个构造函数的类型,您可能会更清楚地看到它:

data Edit where
  Change :: Char -> Char -> Edit
  Copy   :: Char -> Edit
  Delete :: Char -> Edit
  Insert :: Char -> Edit
  deriving (Eq, Show)

因此,传递给filter的函数\x -> x /= Copy具有以下推断类型,因为您正试图将x与函数Copy进行比较:< / p>

(Eq (Char -> Edit))
  => (Char -> Edit) -> Bool

filter具有这种类型:

filter :: (a -> Bool) -> [a] -> [a]

由于推论a等于Char -> Edit,因此推断filter (\x -> x /= Copy)的类型为:

(Eq (Char -> Edit))
  => [Char -> Edit] -> [Char -> Edit]

当然不是您想要的,这有两个原因-首先,它不表达您想要的内容(不是使用Copy构造函数构造的编辑内容),其次,它可以无法工作,因为没有实例Eq (Char -> Edit)可让您比较函数,也无法编写一个实例,因为函数不可比。

如果要检查在调用Edit时是否使用Copy构造了filter类型的值,则应改用 pattern-matching 。一种简单的方法是编写一个函数:

isCopy :: Edit -> Bool
isCopy edit = case edit of
  {- your implementation here -}

然后在filter的情况下使用它:

filter (\x -> {- your condition here -})

并且它将根据需要输入[Edit] -> [Edit]类型。除了编写单独的函数isCopy之外,您还可以使用case表达式编写此内联代码:

filter (\x -> case x of
  {- your implementation here -})

解决此问题的另一种方法是通过编写函数cost1 :: Edit -> Int将其分解为较小的部分,该函数返回单个编辑的成本:

cost1 :: Edit -> Int
cost1 edit = case edit of
  Change _ _ -> 1
  Copy _ -> 0
  {- remaining cases -}

然后cost可以使用map或列表理解将cost1应用于整个编辑列表,并获取结果的sum