来自 Data.Map 的函数 -> 可能作为 class 实例。对如何实施感到困惑

Function from Data.Map -> Maybe as a class instance. Confused about how to implement

当我完成 cis 194 (week 5) 时,我遇到了一个问题,它同时向我介绍了两个新概念,但我很难让它至少输出正确的类型。

我的目标是在最下面声明的实例中实现var,但是我从来没有使用过作为函数的实例,也没有使用过Data.Map,所以我我不太清楚我的解决方案语法应该是什么样子。

{-# LANGUAGE FlexibleInstances #-}
import qualified Data.Map as M

class HasVars a where
    var :: String -> a

-- | This instance allows variables to be interpreted as functions from a
--   mapping of variables to Integer values to (possibly) Integer values
instance HasVars (M.Map String Integer -> Maybe Integer) where
    -- not sure how to implement var here

所以,我想出了一个至少可以编译的东西。当我试图通过反复使用 Maybe 作为构造函数来解决这个问题时,我不必要地给自己造成了一些困惑,并茫然地盯着它未定义的错误消息。 JustMaybe 的构造函数,Maybe 不是构造函数;太多次了...

其次,我使用 lookup ... 而不是 M.lookup ... 完全空白,导致意外的类型结果。

抛开那些绊脚石,这是我尝试过的方法

instance HasVars (M.Map String Integer -> Maybe Integer) where
    var str = M.lookup str -- can be Eta-reduced

这可以编译,但对我来说没有太大意义的是,根据实例声明,我不应该提供键值 Map 吗? M.lookup 会返回一个 Maybe Integer,但似乎我给它的还不够,因为它需要一个密钥 Map,我好像没有Map。也许我对 class 实例如何工作的理解是错误的。

所以当你有

class HasVars a where
    var :: String -> a

这意味着,对于任何实例 a,您都有一个函数 var :: String -> a

所以,如果 Map String Integer -> Maybe Integer 是一个实例,那么这意味着你必须提供一个函数:

var :: String -> (Map String Integer -> Maybe Integer)

记住(->)是从右边关联的,所以这里的括号是可选的--

var :: String -> Map String Integer -> Maybe Integer

因此,var 是一个接受 StringMap 以及 return 和 Maybe Integer 的函数。写吧!

instance HasVars (Map String Integer -> Maybe Integer) where
    -- var :: String -> Map String Integer -> Maybe Integer
    var str mp = M.lookup str mp

这有效!


编辑:问题在回答

我看到你想知道为什么

var str = M.lookup str

有效。请记住 M.lookup str 不是 return 和 Maybe Integer。它 return 是 Map String Integer -> Maybe Integera 应该是什么……正是您想要的。 var str 现在是一个接受 map 和 returns a Maybe Integer.

的函数

M.lookup str 没有地图,是的,所以它不能 return 一个 Maybe Integer。但它是一个 Map String Integer -> Maybe Integer。所以 var "hello" 现在是 Map String Integer -> Maybe Integervar "hello" 给你一个函数,它接受一个地图和 returns 一个 Maybe Integer。所以如果你给 var "hello" 一张地图,比如 var "hello" mp,那么你会得到 Maybe Integer :D