从Haskell中的函数中提取



我有以下数据类型

type Store = Loc -> Z
type Loc = Z
type Z = Integer

其中的基本思想是商店将Location映射到一个整数。每个位置都由其自己的整数标识符表示。

现在,在任务的其他地方,我有一个Store(Loc->Z),我需要从中提取整数。所以我需要一个函数,它接收一个存储并只返回Z部分。

funExtract :: Store -> Z
funExtract sto = ???

就我的一生而言,我所尝试的一切都会带来某种错误。如有任何帮助,我们将不胜感激。感谢

是的,通过构建函数来模仿商店。这是编程语言类中常见的一个很好的练习。您将需要两个函数,一个用于构建存储,另一个用于提取值。要构建一个存储,您需要原始存储、要插入的元素和位置:

type Store = Loc -> Z
type Loc = Z
type Z = Integer
extend :: Loc -> Z -> Store -> Store
extend loc val st = look ->
  if look == loc then val else st look

extend中,我们只定义了一个函数,如果您将值传递给匹配的位置,该函数将返回值。如果位置不匹配,那么位置可能是在原始存储中定义的,所以我们将该存储应用于查找。

现在要实现查找:

funExtract :: Store -> Loc -> Z
funExtract sto loc = sto loc

注意到了吗?您提出的是将存储系统实现为一个函数,因此查找只是函数应用程序。由于我们不会返回具有empty值的东西,如Maybe a类型,因此如果位置不在我们的商店中,我们将需要采取严厉措施。让我们在空商店上查找一个错误:

emptyStore :: Store
emptyStore loc = error $ "Can not find location " ++ show loc ++ "."

下面我在GHCi中玩了一点这个结构。

*Main> let sto = extend 1 31337 (extend 0 1337 emptyStore)
*Main> sto 0
1337
*Main> sto 1
31337
*Main> sto 2
*** Exception: Can not find location 2.

Store是一种函数类型,它获取一个位置并将其映射到一个整数。要实现任务,您应该将所有位置存储在funExtract中,或者使用像Data.Map这样的外部存储。以下是如何做到这一点。

import qualified Data.Map as DM
type Store = Loc -> Z
type Loc   = Z
type Z     = Integer
-- First way --
funExtract :: Store
funExtract 1 = 2
funExtract 2 = 9
-- here could be more values:          --
--   for each new values a new pattern --
funExtract 108 = 17
{- This solution doesn't allow to add new locations
   at the runtime. Look at Thomas's answer to understand
   how to do this with function as a container. Or look
   at the second way:                                    -}
-- Second way --
-- To add new location, add it to locStorage using
-- functions from Data.Map.
locStorage :: DM.Map Loc Z
locStorage = DM.fromList [(1, 2), (2, 9), {- ... -} (108, 17)]
-- `funExtract` becomes just a query
funExtract' :: Store
funExtract' = (DM.!) locStorage

相关内容

  • 没有找到相关文章

最新更新