2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[Haskell] where 句は式でない

Last updated at Posted at 2023-10-24

where 句は式でないため、print (x where x = 23 :: Int) のような書き方はできません (parse error on input ‘where’ が発生します) 。

本記事では、where 句の書き方についてまとめます。

1. where 句を書ける場所

モジュール定義、クラス宣言およびインスタンス宣言を除くと、where 句を書ける場所は以下の 2 種類のみです:

  • 関数定義を含む変数束縛
    • すなわち where の左側に = が必須
  • case 式の選択肢
    • すなわち where の左側に -> が必須

ちなみに無名関数では変数束縛しないため (\x -> x * y where y = 23 :: Int) のような書き方はできません。

参考「4.4.3 Function and Pattern Bindings - 4 Declarations and Bindings
参考「3.13 Case Expressions - 3 Expressions
参考「10 Syntax Reference

2. where 句の書き方

2.1. 基本

f :: Int -> Int
f x = y
  where
    y = x * 42

main :: IO ()
main = do
    print $ f 23
data T = Foo | Bar

main :: IO ()
main = do

    let x = Foo :: T

    print $ case x of
        Foo -> y where y = 23 :: Int
        Bar -> y where y = 42 :: Int

2.2. ガードを用いる場合

複数のガードを付けている場合でも、1 つの変数束縛および case 式の 1 つの選択肢に対して 1 つの where を使用することができます。

f :: Int -> Int
f x
    | x >= 0    = y
    | otherwise = - y
  where
    y = x * 42

main :: IO ()
main = do
    print $ f 23

case 式の選択肢の場合でも変数束縛の場合と同様ですが、case 式内でガードを用いるとコードがややこしくなるため、そもそも関数を分ける等して case 式内でガードを用いない方が良いかもしれません。

main :: IO ()
main = do

    let x = 23 :: Int

    print $ case x of
        y
            | y >= 0    -> z
            | otherwise -> - z
          where
            z = y * 42 :: Int

2.3. do 式内で where 句を書く場合

do 式に続けて where を書くと do 式内でなく do 式外に書くのと同じ意味になります。

main :: IO ()
main = do
    print x
  where
    x = 23 :: Int
意味
main :: IO ()
main = f
  where
    f = do
        print x
    x = 23 :: Int

do 式内の let による変数束縛で where 句を使用することで、do 式内で where 句を書くことができます。

main :: IO ()
main = do
    let x = y * 42
          where
            y = 23 :: Int
    print x

2.4. どうしても式内で where 句を書きたい場合

case () of _ -> で始まる case 式を用いることで、式内で where 句を書くことができます。

main :: IO ()
main = do

    print (case () of _ -> x where x = 23 :: Int)

    print
        $ (\x -> case () of _ -> x * y where y = 42 :: Int)
        (23 :: Int)
2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?