Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell-模式匹配语法糖和where_Haskell - Fatal编程技术网

Haskell-模式匹配语法糖和where

Haskell-模式匹配语法糖和where,haskell,Haskell,我通常有这样一种模式的功能: f :: a -> b f x = case x of ... -> g ... ... -> g ... ... ... -> g ... where g = ... 几乎在这种情况下,有一种语法上的糖分: f :: a -> b f ... = g ... f ... = g ... ... f ... = g ... 不幸的是,我无法将我的附加到它的位置:我显然会得到一堆不在范围内的s。 我可以使g成为一个

我通常有这样一种模式的功能:

f :: a -> b
f x = case x of
  ... -> g ...
  ... -> g ...
  ...
  ... -> g ...
  where g = ...
几乎在这种情况下,有一种语法上的糖分:

f :: a -> b
f ... = g ...
f ... = g ...
...
f ... = g ...
不幸的是,我无法将我的
附加到它的
位置:我显然会得到一堆
不在范围内的
s。
我可以使
g
成为一个单独的函数,但这并不好:我的模块的名称空间将被实用函数污染。
有解决办法吗?

没有,没有解决办法。当这样的函数有多个子句时,它们不能共享
where
-子句。您唯一的选择是使用case语句,或执行以下操作:

f x =
  go x
  where
    go ... = g ...
    go ... = g ...
    g = ...

…如果出于某种原因您真的想使用函数形式。

我认为您的第一个示例一点也不错。唯一的语法权重是
案例x,加上
->
,而不是
=
;后者被以下事实所抵消:您可以省略每个子句的函数名。事实上,即使是dflemstr提出的
go
helper函数在语法上也更重


诚然,与正常的function子句语法相比,它有点不一致,但这可能是一件好事:它在视觉上更精确地界定了
x
可用的范围。

您最初的解决方案似乎是最好的,也是唯一的解决方法。从语法上讲,它不比函数参数上的直接模式匹配更重,甚至更轻

f = g . h  -- h is most of your original f
  where h ... = ...
        h ... = ...
        g = 
但万一您需要的只是检查前提条件而不是模式匹配,请不要忘记防护装置,它允许您自由访问
where
范围。但实际上,我认为您的
解决方案没有什么不好的地方

f :: a -> b
f a
  | a == 2    = ...
  | isThree a = ...
  | a >= 4    = ...
  | otherwise = ...
  where isThree x = x == 3

从Haskell 2010开始,或通过GHC,您还可以:

f x 
    | m1 <- x = g
    | m2 <- x = g
    ...
    where g =

假设您在case语句的大多数(如果不是全部)不同分支上都一致地使用
g
,是否安全

假设
f::a->b
对于一些
a
b
(可能是多态的),
g
必然是
c->d
形式的函数,这意味着必须有一种方法从
a
中一致地提取
c
。称之为
getC::a->c
。在这种情况下,解决方案是简单地使用
h。GgetC
适用于所有情况,其中
h::d->b

但是假设你不能总是从
a
中得到
c
。也许
a
的形式是
fc
,其中
f
函子
?然后您可以
fmap g::fc->fd
,然后以某种方式将
fd
转换为a
b


这里有点杂乱无章,但是当我看到您似乎在每个分支上应用
g
时,我首先想到的是
fmap

使用
LambdaCase
,您也可以这样做:

{-# language LambdaCase #-}

f :: a -> b
f = \case
  ... -> g ...
  ... -> g ...
  ...
  ... -> g ...
  where g = ...

用于定义函数的等式语法似乎是一种不必要的噱头。我认为OP是在寻找一个通用的解决方案,来解决
g
可能出现在任何等式的RHS上的任何地方(或者根本不出现)的问题。是的,我觉得这个问题模棱两可,并给出了尚未回答的案例的答案。您不必导出
g
,因此名称空间污染只是您自己模块中的一个问题。
{-# language LambdaCase #-}

f :: a -> b
f = \case
  ... -> g ...
  ... -> g ...
  ...
  ... -> g ...
  where g = ...