函数的类型类实例

dar*_*ake 2 haskell

我正在研究CIS 194的作业问题.
我被困在家庭作业5,问题6.

类型ExprHasVars用于表示包含变量的任何表达式的表达式和类型类.
该问题要求实现Exprfor 的实例M.Map String Integer -> Maybe Integer,其中MData.Map.

class Expr a where 
  add :: a -> a -> a
  mul :: a -> a -> a
  lit :: Integer -> a
Run Code Online (Sandbox Code Playgroud)

下面是实例代码ExprInteger.

instance Expr Integer where
  add m n = m + n
  mul m n = m * n
  lit m = m 
Run Code Online (Sandbox Code Playgroud)

对于HasVars函数的实例,

instance HasVars (M.Map String Integer -> Maybe Integer) where
   var s  = M.lookup s 
Run Code Online (Sandbox Code Playgroud)

我很困惑如何Expr为函数类型创建实例.如何进行模式匹配或从函数中提取值?类型是a-> a -> a,所以我没有Map提取值和varShowVars用于转换String为所述函数.

我没有提出问题的其他部分的解决方案,因为它可能包含剧透.

lef*_*out 8

好吧,首先写出签名,以便清楚应该是什么东西.为了使它更具可读性,

type MS2I = M.Map String Integer
type Integer' = Maybe Integer
Run Code Online (Sandbox Code Playgroud)

然后

add :: (MS2I -> Integer') -> (MS2I -> Integer') -> (MS2I -> Integer')
Run Code Online (Sandbox Code Playgroud)

所以你可以先开始吧

add m n = o
 where m, n, o :: MS2I -> Integer'
Run Code Online (Sandbox Code Playgroud)

o是一个采用地图的函数......您可以定义:

add m n = o
 where o ms2i = ...
Run Code Online (Sandbox Code Playgroud)

那时你就有了一张地图.您可以将其提供给参数:

add m n = o
 where o ms2i = let i1 = m ms2i
                    i2 = n ms2i
                    i1, i2 :: Integer'
                in ...?   
Run Code Online (Sandbox Code Playgroud)

其余应该是显而易见的,你只需要将两个结合Maybe Integer到一个新的.(最好用Applicative.)

有趣和参考,这是一个超级浓缩版本:

import Control.Arrow
instance Expr (Kleisli Maybe MS2I Integer) where
  add m n = arr (uncurry(+)) . (m&&&n)
Run Code Online (Sandbox Code Playgroud)

  • @dare_take`lit`可能会创建一个表达式,这意味着它是常量,所以让它采用map参数但忽略它. (2认同)